View Javadoc

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   * An abstract base class for HTTP messages (i.e. Request and Response) with support for
16   * header and entity management.
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 }