1 package com.atlassian.httpclient.apache.httpcomponents;
2
3 import com.atlassian.fugue.Option;
4 import com.atlassian.httpclient.api.Message;
5 import org.apache.http.util.CharArrayBuffer;
6
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.io.Reader;
11 import java.nio.charset.Charset;
12 import java.util.Map;
13
14
15
16
17
18 abstract class DefaultMessage implements Message {
19 private final InputStream entityStream;
20 private final Headers headers;
21 private final long maxEntitySize;
22 private boolean hasRead;
23
24 public DefaultMessage(final Headers headers, final InputStream entityStream, Option<Long> maxEntitySize) {
25 this.maxEntitySize = maxEntitySize.getOrElse((long) Integer.MAX_VALUE);
26 this.headers = headers;
27 this.entityStream = entityStream;
28 }
29
30 public String getContentType() {
31 return headers.getContentType();
32 }
33
34 public String getContentCharset() {
35 return headers.getContentCharset();
36 }
37
38 public String getAccept() {
39 return headers.getHeader("Accept");
40 }
41
42 public InputStream getEntityStream() throws IllegalStateException {
43 checkRead();
44 return entityStream;
45 }
46
47 public String getEntity() throws IllegalStateException, IllegalArgumentException {
48 String entity = null;
49 if (hasEntity()) {
50 checkValidSize();
51 final String charsetAsString = getContentCharset();
52 final Charset charset = charsetAsString != null ? Charset.forName(charsetAsString) : Charset.forName(
53 "UTF-8");
54 try {
55 InputStream instream = getEntityStream();
56 if (instream == null) {
57 return null;
58 }
59 try {
60 int bufferLength = 4096;
61 String lengthHeader = getHeader("Content-Length");
62 if (lengthHeader != null) {
63 bufferLength = Integer.parseInt(lengthHeader);
64 }
65
66 Reader reader = new InputStreamReader(instream, charset);
67 CharArrayBuffer buffer = new CharArrayBuffer(bufferLength);
68 char[] tmp = new char[1024];
69 int l;
70 while ((l = reader.read(tmp)) != -1) {
71 if (buffer.length() + l > maxEntitySize) {
72 throw new IllegalArgumentException("HTTP entity too large to be buffered in memory");
73 }
74 buffer.append(tmp, 0, l);
75 }
76 return buffer.toString();
77 } finally {
78 instream.close();
79 }
80 } catch (IOException e) {
81 throw new IllegalStateException("Unable to convert response body to String", e);
82 }
83 }
84 return entity;
85 }
86
87 public boolean hasEntity() {
88 return entityStream != null;
89 }
90
91 public boolean hasReadEntity() {
92 return hasRead;
93 }
94
95 public Map<String, String> getHeaders() {
96 return headers.getHeaders();
97 }
98
99 public String getHeader(String name) {
100 return headers.getHeader(name);
101 }
102
103 public Message validate() {
104 if (hasEntity() && headers.getContentType() == null) {
105 throw new IllegalStateException("Property contentType must be set when entity is present");
106 }
107 return this;
108 }
109
110 private void checkRead() throws IllegalStateException {
111 if (entityStream != null) {
112 if (hasRead) {
113 throw new IllegalStateException("Entity may only be accessed once");
114 }
115 hasRead = true;
116 }
117 }
118
119 private void checkValidSize() throws IllegalArgumentException {
120 Integer contentLength;
121 String lengthHeader = getHeader("Content-Length");
122 if (lengthHeader != null) {
123 contentLength = Integer.parseInt(lengthHeader);
124 if (contentLength > maxEntitySize) {
125 throw new IllegalArgumentException("HTTP entity too large to be buffered in memory");
126 }
127 }
128 }
129 }