1 /* 2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net.http; 27 28 import java.util.List; 29 import java.util.Map; 30 import java.util.Optional; 31 import java.util.OptionalLong; 32 import static java.util.Collections.emptyList; 33 import static java.util.Collections.unmodifiableList; 34 import static java.util.Objects.requireNonNull; 35 36 /** 37 * A read-only view of a set of HTTP headers. 38 * 39 * <p> An {@code HttpHeaders} is not created directly, but rather returned from 40 * an {@link HttpResponse HttpResponse}. Specific HTTP headers can be set for 41 * {@linkplain HttpRequest requests} through the one of the request builder's 42 * {@link HttpRequest.Builder#header(String, String) headers} methods. 43 * 44 * <p> The methods of this class ( that accept a String header name ), and the 45 * Map returned by the {@link #map() map} method, operate without regard to 46 * case when retrieving the header value. 47 * 48 * <p> {@code HttpHeaders} instances are immutable. 49 * 50 * @since 11 51 */ 52 public abstract class HttpHeaders { 53 54 /** 55 * Creates an HttpHeaders. 56 */ 57 protected HttpHeaders() {} 58 59 /** 60 * Returns an {@link Optional} containing the first value of the given named 61 * (and possibly multi-valued) header. If the header is not present, then 62 * the returned {@code Optional} is empty. 63 * 64 * @implSpec 65 * The default implementation invokes 66 * {@code allValues(name).stream().findFirst()} 67 * 68 * @param name the header name 69 * @return an {@code Optional<String>} for the first named value 70 */ 71 public Optional<String> firstValue(String name) { 72 return allValues(name).stream().findFirst(); 73 } 74 75 /** 76 * Returns an {@link OptionalLong} containing the first value of the 77 * named header field. If the header is not present, then the Optional is 78 * empty. If the header is present but contains a value that does not parse 79 * as a {@code Long} value, then an exception is thrown. 80 * 81 * @implSpec 82 * The default implementation invokes 83 * {@code allValues(name).stream().mapToLong(Long::valueOf).findFirst()} 84 * 85 * @param name the header name 86 * @return an {@code OptionalLong} 87 * @throws NumberFormatException if a value is found, but does not parse as 88 * a Long 89 */ 90 public OptionalLong firstValueAsLong(String name) { 91 return allValues(name).stream().mapToLong(Long::valueOf).findFirst(); 92 } 93 94 /** 95 * Returns an unmodifiable List of all of the values of the given named 96 * header. Always returns a List, which may be empty if the header is not 97 * present. 98 * 99 * @implSpec 100 * The default implementation invokes, among other things, the 101 * {@code map().get(name)} to retrieve the list of header values. 102 * 103 * @param name the header name 104 * @return a List of String values 105 */ 106 public List<String> allValues(String name) { 107 requireNonNull(name); 108 List<String> values = map().get(name); 109 // Making unmodifiable list out of empty in order to make a list which 110 // throws UOE unconditionally 111 return values != null ? values : unmodifiableList(emptyList()); 112 } 113 114 /** 115 * Returns an unmodifiable multi Map view of this HttpHeaders. 116 * 117 * @return the Map 118 */ 119 public abstract Map<String, List<String>> map(); 120 121 /** 122 * Tests this HTTP headers instance for equality with the given object. 123 * 124 * <p> If the given object is not an {@code HttpHeaders} then this 125 * method returns {@code false}. Two HTTP headers are equal if each 126 * of their corresponding {@linkplain #map() maps} are equal. 127 * 128 * <p> This method satisfies the general contract of the {@link 129 * Object#equals(Object) Object.equals} method. 130 * 131 * @param obj the object to which this object is to be compared 132 * @return {@code true} if, and only if, the given object is an {@code 133 * HttpHeaders} that is equal to this HTTP headers 134 */ 135 public final boolean equals(Object obj) { 136 if (!(obj instanceof HttpHeaders)) 137 return false; 138 HttpHeaders that = (HttpHeaders)obj; 139 return this.map().equals(that.map()); 140 } 141 142 /** 143 * Computes a hash code for this HTTP headers instance. 144 * 145 * <p> The hash code is based upon the components of the HTTP headers 146 * {@link #map() map}, and satisfies the general contract of the 147 * {@link Object#hashCode Object.hashCode} method. 148 * 149 * @return the hash-code value for this HTTP headers 150 */ 151 public final int hashCode() { 152 return map().hashCode(); 153 } 154 155 /** 156 * Returns this HTTP headers as a string. 157 * 158 * @return a string describing the HTTP headers 159 */ 160 @Override 161 public String toString() { 162 StringBuilder sb = new StringBuilder(); 163 sb.append(super.toString()).append(" { "); 164 sb.append(map()); 165 sb.append(" }"); 166 return sb.toString(); 167 } 168 }