1package com.xtremelabs.robolectric.tester.org.apache.http;
2
3import com.xtremelabs.robolectric.shadows.StatusLineStub;
4import org.apache.http.Header;
5import org.apache.http.HeaderIterator;
6import org.apache.http.HttpEntity;
7import org.apache.http.HttpVersion;
8import org.apache.http.ProtocolVersion;
9import org.apache.http.StatusLine;
10import org.apache.http.params.BasicHttpParams;
11import org.apache.http.params.HttpParams;
12
13import java.io.ByteArrayInputStream;
14import java.io.IOException;
15import java.io.InputStream;
16import java.io.OutputStream;
17import java.util.ArrayList;
18import java.util.Collections;
19import java.util.List;
20import java.util.NoSuchElementException;
21
22public class TestHttpResponse extends HttpResponseStub {
23
24    private int statusCode;
25    private byte[] responseBody;
26    private TestStatusLine statusLine = new TestStatusLine();
27    private TestHttpEntity httpEntity = new TestHttpEntity();
28    private int openEntityContentStreamCount = 0;
29    private Header[] headers = new Header[0];
30    private HttpParams params = new BasicHttpParams();
31
32    public TestHttpResponse() {
33        this.statusCode = 200;
34        this.responseBody = new byte[0];
35    }
36
37    public TestHttpResponse(int statusCode, String responseBody) {
38        this.statusCode = statusCode;
39        this.responseBody = responseBody.getBytes();
40    }
41
42    public TestHttpResponse(int statusCode, String responseBody, Header... headers) {
43        this(statusCode, responseBody.getBytes(), headers);
44    }
45
46    public TestHttpResponse(int statusCode, byte[] responseBody, Header... headers) {
47        this.statusCode = statusCode;
48        this.responseBody = responseBody.clone();
49        this.headers = headers;
50    }
51
52    protected void setResponseBody(String responseBody) {
53        this.responseBody = responseBody.getBytes();
54    }
55
56    @Override public StatusLine getStatusLine() {
57        return statusLine;
58    }
59
60    @Override public HttpEntity getEntity() {
61        return httpEntity;
62    }
63
64    @Override public Header[] getAllHeaders() {
65        return headers;
66    }
67
68    @Override public Header getFirstHeader(String s) {
69        for (Header h : headers) {
70            if (s.equalsIgnoreCase(h.getName())) {
71                return h;
72            }
73        }
74        return null;
75    }
76
77    @Override public Header getLastHeader(String s) {
78        for (int i = headers.length -1; i >= 0; i--) {
79            if (headers[i].getName().equalsIgnoreCase(s)) {
80                return headers[i];
81            }
82        }
83        return null;
84    }
85
86    @Override public Header[] getHeaders(String s) {
87        List<Header> found = new ArrayList<Header>();
88        for (Header h : headers) {
89            if (h.getName().equalsIgnoreCase(s)) found.add(h);
90        }
91        return found.toArray(new Header[found.size()]);
92    }
93
94    @Override
95    public void addHeader(Header header) {
96        List<Header> temp = new ArrayList<Header>();
97        Collections.addAll(temp, headers);
98        temp.add(header);
99        headers = temp.toArray(new Header[temp.size()]);
100    }
101
102    @Override
103    public void setHeader(Header newHeader) {
104        for (int i = 0; i < headers.length; i++) {
105            Header header = headers[i];
106            if (header.getName().equals(newHeader.getName())) {
107                headers[i] = newHeader;
108                return;
109            }
110        }
111    }
112
113    @Override public HeaderIterator headerIterator() {
114        return new HeaderIterator() {
115            int index = 0;
116
117            @Override public boolean hasNext() {
118                return index < headers.length;
119            }
120
121            @Override public Header nextHeader() {
122                if (index >= headers.length) throw new NoSuchElementException();
123                return headers[index++];
124            }
125
126            @Override public Object next() {
127                return nextHeader();
128            }
129
130            @Override public void remove() {
131                throw new UnsupportedOperationException();
132            }
133        };
134    }
135
136
137    @Override public HeaderIterator headerIterator(final String s) {
138        return new HeaderIterator() {
139            int index = 0;
140
141            @Override public boolean hasNext() {
142                return nextIndex() != -1;
143            }
144
145            private int nextIndex() {
146                for (int i = index; i<headers.length; i++) {
147                    if (headers[i].getName().equalsIgnoreCase(s)) {
148                        return i;
149                    }
150                }
151                return -1;
152            }
153
154            @Override public Header nextHeader() {
155                index = nextIndex();
156                if (index == -1) throw new NoSuchElementException();
157                return headers[index++];
158            }
159
160            @Override public Object next() {
161                return nextHeader();
162            }
163
164            @Override public void remove() {
165                throw new UnsupportedOperationException();
166            }
167        };
168    }
169
170    @Override public boolean containsHeader(String s) {
171        return getFirstHeader(s) != null;
172
173    }
174
175    @Override public HttpParams getParams() {
176        return params;
177    }
178
179    @Override public void setParams(HttpParams httpParams) {
180        this.params = httpParams;
181    }
182
183    public boolean entityContentStreamsHaveBeenClosed() {
184        return openEntityContentStreamCount == 0;
185    }
186
187    public class TestHttpEntity extends HttpEntityStub {
188
189        private ByteArrayInputStream inputStream;
190
191        @Override public long getContentLength() {
192            return responseBody.length;
193        }
194
195        @Override public Header getContentType() {
196            for (Header header : headers) {
197                if (header.getName().equals("Content-Type")) {
198                    return header;
199                }
200            }
201            return null;
202        }
203
204        @Override public boolean isStreaming() {
205            return true;
206        }
207
208        @Override public boolean isRepeatable() {
209            return true;
210        }
211
212        @Override public InputStream getContent() throws IOException, IllegalStateException {
213            openEntityContentStreamCount++;
214            inputStream = new ByteArrayInputStream(responseBody) {
215                @Override
216                public void close() throws IOException {
217                    openEntityContentStreamCount--;
218                    super.close();
219                }
220            };
221            return inputStream;
222        }
223
224        @Override public void writeTo(OutputStream outputStream) throws IOException {
225            outputStream.write(responseBody);
226        }
227
228        @Override public void consumeContent() throws IOException {
229        }
230    }
231
232    public class TestStatusLine extends StatusLineStub {
233        @Override public ProtocolVersion getProtocolVersion() {
234            return new HttpVersion(1, 0);
235        }
236
237        @Override public int getStatusCode() {
238            return statusCode;
239        }
240
241        @Override public String getReasonPhrase() {
242            return "HTTP status " + statusCode;
243        }
244
245        @Override public String toString() {
246            return "TestStatusLine[" + getReasonPhrase() + "]";
247        }
248    }
249}
250