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