1/*
2 * Copyright 2008 Sean Sullivan
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
17package net.oauth.client.httpclient4;
18
19import java.io.IOException;
20import java.io.InputStream;
21import java.net.URL;
22import java.util.ArrayList;
23import java.util.List;
24import java.util.Map;
25import net.oauth.OAuth;
26import net.oauth.client.ExcerptInputStream;
27import net.oauth.http.HttpMessage;
28import net.oauth.http.HttpResponseMessage;
29import org.apache.http.Header;
30import org.apache.http.HttpEntityEnclosingRequest;
31import org.apache.http.HttpResponse;
32import org.apache.http.client.methods.HttpRequestBase;
33
34/**
35 * An HttpResponse, encapsulated as an OAuthMessage.
36 *
37 * This class relies on <a href="http://hc.apache.org">Apache HttpClient</a>
38 * version 4.
39 *
40 * @author Sean Sullivan
41 * @hide
42 */
43public class HttpMethodResponse extends HttpResponseMessage
44{
45
46    /**
47     * Construct an OAuthMessage from the HTTP response, including parameters
48     * from OAuth WWW-Authenticate headers and the body. The header parameters
49     * come first, followed by the ones from the response body.
50     */
51    public HttpMethodResponse(HttpRequestBase request, HttpResponse response, byte[] requestBody,
52            String requestEncoding) throws IOException
53    {
54        super(request.getMethod(), new URL(request.getURI().toString()));
55        this.httpRequest = request;
56        this.httpResponse = response;
57        this.requestBody = requestBody;
58        this.requestEncoding = requestEncoding;
59        this.headers.addAll(getHeaders());
60    }
61
62    private final HttpRequestBase httpRequest;
63    private final HttpResponse httpResponse;
64    private final byte[] requestBody;
65    private final String requestEncoding;
66
67    @Override
68    public int getStatusCode()
69    {
70        return httpResponse.getStatusLine().getStatusCode();
71    }
72
73    @Override
74    public InputStream openBody() throws IOException
75    {
76        return httpResponse.getEntity().getContent();
77    }
78
79    private List<Map.Entry<String, String>> getHeaders()
80    {
81        List<Map.Entry<String, String>> headers = new ArrayList<Map.Entry<String, String>>();
82        Header[] allHeaders = httpResponse.getAllHeaders();
83        if (allHeaders != null) {
84            for (Header header : allHeaders) {
85                headers.add(new OAuth.Parameter(header.getName(), header.getValue()));
86            }
87        }
88        return headers;
89    }
90
91    /** Return a complete description of the HTTP exchange. */
92    @Override
93    public void dump(Map<String, Object> into) throws IOException
94    {
95        super.dump(into);
96        {
97            StringBuilder request = new StringBuilder(httpRequest.getMethod());
98            request.append(" ").append(httpRequest.getURI().getPath());
99            String query = httpRequest.getURI().getQuery();
100            if (query != null && query.length() > 0) {
101                request.append("?").append(query);
102            }
103            request.append(EOL);
104            for (Header header : httpRequest.getAllHeaders()) {
105                request.append(header.getName()).append(": ").append(header.getValue()).append(EOL);
106            }
107            if (httpRequest instanceof HttpEntityEnclosingRequest) {
108                HttpEntityEnclosingRequest r = (HttpEntityEnclosingRequest) httpRequest;
109                long contentLength = r.getEntity().getContentLength();
110                if (contentLength >= 0) {
111                    request.append("Content-Length: ").append(contentLength).append(EOL);
112                }
113            }
114            request.append(EOL);
115            if (requestBody != null) {
116                request.append(new String(requestBody, requestEncoding));
117            }
118            into.put(REQUEST, request.toString());
119        }
120        {
121            StringBuilder response = new StringBuilder();
122            String value = httpResponse.getStatusLine().toString();
123            response.append(value).append(EOL);
124            for (Header header : httpResponse.getAllHeaders()) {
125                String name = header.getName();
126                value = header.getValue();
127                response.append(name).append(": ").append(value).append(EOL);
128            }
129            response.append(EOL);
130            if (body != null) {
131                response.append(new String(((ExcerptInputStream) body).getExcerpt(),
132                        getContentCharset()));
133            }
134            into.put(HttpMessage.RESPONSE, response.toString());
135        }
136    }
137}
138