1 /* 2 * Copyright (C) 2011 The Android Open Source Project 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 17 package com.android.volley; 18 19 import java.net.HttpURLConnection; 20 import java.util.ArrayList; 21 import java.util.Collections; 22 import java.util.List; 23 import java.util.Map; 24 import java.util.TreeMap; 25 26 /** 27 * Data and headers returned from {@link Network#performRequest(Request)}. 28 */ 29 public class NetworkResponse { 30 31 /** 32 * Creates a new network response. 33 * @param statusCode the HTTP status code 34 * @param data Response body 35 * @param headers Headers returned with this response, or null for none 36 * @param notModified True if the server returned a 304 and the data was already in cache 37 * @param networkTimeMs Round-trip network time to receive network response 38 * @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor 39 * cannot handle server responses containing multiple headers with the same name. 40 * This constructor may be removed in a future release of Volley. 41 */ 42 @Deprecated 43 public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers, 44 boolean notModified, long networkTimeMs) { 45 this(statusCode, data, headers, toAllHeaderList(headers), notModified, networkTimeMs); 46 } 47 48 /** 49 * Creates a new network response. 50 * @param statusCode the HTTP status code 51 * @param data Response body 52 * @param notModified True if the server returned a 304 and the data was already in cache 53 * @param networkTimeMs Round-trip network time to receive network response 54 * @param allHeaders All headers returned with this response, or null for none 55 */ 56 public NetworkResponse(int statusCode, byte[] data, boolean notModified, long networkTimeMs, 57 List<Header> allHeaders) { 58 this(statusCode, data, toHeaderMap(allHeaders), allHeaders, notModified, networkTimeMs); 59 } 60 61 /** 62 * Creates a new network response. 63 * @param statusCode the HTTP status code 64 * @param data Response body 65 * @param headers Headers returned with this response, or null for none 66 * @param notModified True if the server returned a 304 and the data was already in cache 67 * @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor 68 * cannot handle server responses containing multiple headers with the same name. 69 * This constructor may be removed in a future release of Volley. 70 */ 71 @Deprecated 72 public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers, 73 boolean notModified) { 74 this(statusCode, data, headers, notModified, 0); 75 } 76 77 /** 78 * Creates a new network response for an OK response with no headers. 79 * @param data Response body 80 */ 81 public NetworkResponse(byte[] data) { 82 this(HttpURLConnection.HTTP_OK, data, false, 0, Collections.<Header>emptyList()); 83 } 84 85 /** 86 * Creates a new network response for an OK response. 87 * @param data Response body 88 * @param headers Headers returned with this response, or null for none 89 * @deprecated see {@link #NetworkResponse(int, byte[], boolean, long, List)}. This constructor 90 * cannot handle server responses containing multiple headers with the same name. 91 * This constructor may be removed in a future release of Volley. 92 */ 93 @Deprecated 94 public NetworkResponse(byte[] data, Map<String, String> headers) { 95 this(HttpURLConnection.HTTP_OK, data, headers, false, 0); 96 } 97 98 private NetworkResponse(int statusCode, byte[] data, Map<String, String> headers, 99 List<Header> allHeaders, boolean notModified, long networkTimeMs) { 100 this.statusCode = statusCode; 101 this.data = data; 102 this.headers = headers; 103 if (allHeaders == null) { 104 this.allHeaders = null; 105 } else { 106 this.allHeaders = Collections.unmodifiableList(allHeaders); 107 } 108 this.notModified = notModified; 109 this.networkTimeMs = networkTimeMs; 110 } 111 112 /** The HTTP status code. */ 113 public final int statusCode; 114 115 /** Raw data from this response. */ 116 public final byte[] data; 117 118 /** 119 * Response headers. 120 * 121 * <p>This map is case-insensitive. It should not be mutated directly. 122 * 123 * <p>Note that if the server returns two headers with the same (case-insensitive) name, this 124 * map will only contain the last one. Use {@link #allHeaders} to inspect all headers returned 125 * by the server. 126 */ 127 public final Map<String, String> headers; 128 129 /** All response headers. Must not be mutated directly. */ 130 public final List<Header> allHeaders; 131 132 /** True if the server returned a 304 (Not Modified). */ 133 public final boolean notModified; 134 135 /** Network roundtrip time in milliseconds. */ 136 public final long networkTimeMs; 137 138 private static Map<String, String> toHeaderMap(List<Header> allHeaders) { 139 if (allHeaders == null) { 140 return null; 141 } 142 if (allHeaders.isEmpty()) { 143 return Collections.emptyMap(); 144 } 145 Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); 146 // Later elements in the list take precedence. 147 for (Header header : allHeaders) { 148 headers.put(header.getName(), header.getValue()); 149 } 150 return headers; 151 } 152 153 private static List<Header> toAllHeaderList(Map<String, String> headers) { 154 if (headers == null) { 155 return null; 156 } 157 if (headers.isEmpty()) { 158 return Collections.emptyList(); 159 } 160 List<Header> allHeaders = new ArrayList<>(headers.size()); 161 for (Map.Entry<String, String> header : headers.entrySet()) { 162 allHeaders.add(new Header(header.getKey(), header.getValue())); 163 } 164 return allHeaders; 165 } 166 } 167 168