1b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien/*
2b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Copyright 2008 Netflix, Inc.
3b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien *
4b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Licensed under the Apache License, Version 2.0 (the "License");
5b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * you may not use this file except in compliance with the License.
6b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * You may obtain a copy of the License at
7b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien *
8b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien *     http://www.apache.org/licenses/LICENSE-2.0
9b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien *
10b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * Unless required by applicable law or agreed to in writing, software
11b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * distributed under the License is distributed on an "AS IS" BASIS,
12b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * See the License for the specific language governing permissions and
14b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * limitations under the License.
15b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien */
16b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
17b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienpackage net.oauth.client;
18b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
19b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.io.IOException;
20b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.io.InputStream;
21b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.net.HttpURLConnection;
22b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.net.URLConnection;
23b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.util.ArrayList;
24b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.util.List;
25b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport java.util.Map;
26b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.OAuth;
27b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.http.HttpMessage;
28b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienimport net.oauth.http.HttpResponseMessage;
29b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
30b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien/**
31b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * The response part of a URLConnection, encapsulated as an OAuthMessage.
32b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien *
33b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * @author John Kristian
34b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien * @hide
35b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien */
36b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembienpublic class URLConnectionResponse extends HttpResponseMessage {
37b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
38b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    /**
39b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien     * Construct an OAuthMessage from the HTTP response, including parameters
40b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien     * from OAuth WWW-Authenticate headers and the body. The header parameters
41b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien     * come first, followed by the ones from the response body.
42b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien     */
43b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    public URLConnectionResponse(HttpMessage request, String requestHeaders,
44b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            byte[] requestExcerpt, URLConnection connection) throws IOException {
45b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        super(request.method, request.url);
46b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        this.requestHeaders = requestHeaders;
47b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        this.requestExcerpt = requestExcerpt;
48b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        this.requestEncoding = request.getContentCharset();
49b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        this.connection = connection;
50b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        this.headers.addAll(getHeaders());
51b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    }
52b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
53b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    private final String requestHeaders;
54b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    private final byte[] requestExcerpt;
55b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    private final String requestEncoding;
56b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    private final URLConnection connection;
57b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
58b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    @Override
59b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    public int getStatusCode() throws IOException {
60b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        if (connection instanceof HttpURLConnection) {
61b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            return ((HttpURLConnection) connection).getResponseCode();
62b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        }
63b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        return STATUS_OK;
64b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    }
65b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
66b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    @Override
67b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    public InputStream openBody() {
68b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        try {
69b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            return connection.getInputStream();
70b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        } catch (IOException ohWell) {
71b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        }
72b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        return null;
73b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    }
74b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
75b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    private List<Map.Entry<String, String>> getHeaders() {
76b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        List<Map.Entry<String, String>> headers = new ArrayList<Map.Entry<String, String>>();
77b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        boolean foundContentType = false;
78b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        String value;
79b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        for (int i = 0; (value = connection.getHeaderField(i)) != null; ++i) {
80b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            String name = connection.getHeaderFieldKey(i);
81b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            if (name != null) {
82b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                headers.add(new OAuth.Parameter(name, value));
83b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                if (CONTENT_TYPE.equalsIgnoreCase(name)) {
84b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    foundContentType = true;
85b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                }
86b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            }
87b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        }
88b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        if (!foundContentType) {
89b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            headers.add(new OAuth.Parameter(CONTENT_TYPE, connection
90b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    .getContentType()));
91b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        }
92b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        return headers;
93b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    }
94b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    /** Return a complete description of the HTTP exchange. */
95b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    @Override
96b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    public void dump(Map<String, Object> into) throws IOException {
97b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        super.dump(into);
98b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        {
99b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            StringBuilder request = new StringBuilder(requestHeaders);
100b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            request.append(EOL);
101b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            if (requestExcerpt != null) {
102b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                request.append(new String(requestExcerpt, requestEncoding));
103b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            }
104b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            into.put(REQUEST, request.toString());
105b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        }
106b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        {
107b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            HttpURLConnection http = (connection instanceof HttpURLConnection) ? (HttpURLConnection) connection
108b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    : null;
109b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            StringBuilder response = new StringBuilder();
110b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            String value;
111b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            for (int i = 0; (value = connection.getHeaderField(i)) != null; ++i) {
112b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                String name = connection.getHeaderFieldKey(i);
113b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                if (i == 0 && name != null && http != null) {
114b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    String firstLine = "HTTP " + getStatusCode();
115b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    String message = http.getResponseMessage();
116b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    if (message != null) {
117b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                        firstLine += (" " + message);
118b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    }
119b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    response.append(firstLine).append(EOL);
120b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                }
121b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                if (name != null) {
122b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    response.append(name).append(": ");
123b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                    name = name.toLowerCase();
124b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                }
125b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                response.append(value).append(EOL);
126b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            }
127b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            response.append(EOL);
128b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            if (body != null) {
129b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                response.append(new String(((ExcerptInputStream) body)
130b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien                        .getExcerpt(), getContentCharset()));
131b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            }
132b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien            into.put(HttpMessage.RESPONSE, response.toString());
133b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien        }
134b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien    }
135b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien
136b852fcf48a8909164d7f323dd02a35d2a8056a61Nico Sallembien}
137