001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.http.header; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.io.*; 023import java.util.*; 024import java.util.function.*; 025 026import org.apache.http.*; 027import org.apache.http.message.*; 028import org.apache.juneau.annotation.*; 029import org.apache.juneau.assertions.*; 030import org.apache.juneau.commons.utils.*; 031 032/** 033 * Superclass of all headers defined in this package. 034 * 035 * Provides the following features: 036 * <ul class='spaced-list'> 037 * <li> 038 * Default support for various streams and readers. 039 * <li> 040 * Content from {@link Supplier Suppliers}. 041 * <li> 042 * Caching. 043 * <li> 044 * Fluent setters. 045 * <li> 046 * Fluent assertions. 047 * </ul> 048 * 049 * <h5 class='section'>See Also:</h5><ul> 050 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a> 051 * <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a> 052 * </ul> 053 * 054 * @serial exclude 055 */ 056@BeanIgnore 057public class BasicHeader implements Header, Cloneable, Serializable { 058 private static final long serialVersionUID = 1L; 059 private static final HeaderElement[] EMPTY_HEADER_ELEMENTS = {}; 060 061 /** 062 * Static creator. 063 * 064 * @param o The name value pair that makes up the header name and value. 065 * The parameter value. 066 * <br>Any non-String value will be converted to a String using {@link Object#toString()}. 067 * @return A new header bean. 068 */ 069 public static BasicHeader of(NameValuePair o) { 070 return new BasicHeader(o.getName(), o.getValue()); 071 } 072 073 /** 074 * Static creator. 075 * 076 * @param name The parameter name. 077 * @param value 078 * The parameter value. 079 * <br>Can be <jk>null</jk>. 080 * @return A new header bean, or <jk>null</jk> if value is <jk>null</jk>. 081 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 082 */ 083 public static BasicHeader of(String name, Object value) { 084 return value == null ? null : new BasicHeader(name, value); 085 } 086 087 private final String name; 088 private final String stringValue; 089 090 private final Object value; 091 private final Supplier<Object> supplier; 092 093 private HeaderElement[] elements; 094 095 /** 096 * Constructor. 097 * 098 * @param name The parameter name. 099 * @param value 100 * The parameter value. 101 * <br>Any non-String value will be converted to a String using {@link Object#toString()}. 102 * <br>Can also be an <l>Object</l> {@link Supplier}. 103 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 104 */ 105 @SuppressWarnings("unchecked") 106 public BasicHeader(String name, Object value) { 107 assertArg(Utils.ne(name), "Name cannot be empty on header."); // NOAI 108 this.name = name; 109 this.value = value instanceof Supplier ? null : value; 110 this.stringValue = s(value); 111 this.supplier = cast(Supplier.class, value); 112 } 113 114 /** 115 * Constructor with delayed value. 116 * 117 * <p> 118 * Header value is re-evaluated on each call to {@link #getValue()}. 119 * 120 * @param name The header name. 121 * @param value 122 * The supplier of the header value. 123 * <br>Can be <jk>null</jk>. 124 * @throws IllegalArgumentException If name is <jk>null</jk> or empty. 125 */ 126 public BasicHeader(String name, Supplier<Object> value) { 127 assertArg(Utils.ne(name), "Name cannot be empty on header."); // NOAI 128 this.name = name; 129 this.value = null; 130 this.stringValue = null; 131 supplier = value; 132 } 133 134 /** 135 * Copy constructor. 136 * 137 * @param copyFrom The object to copy. 138 */ 139 protected BasicHeader(BasicHeader copyFrom) { 140 this.name = copyFrom.name; 141 this.value = copyFrom.value; 142 this.stringValue = copyFrom.stringValue; 143 this.supplier = copyFrom.supplier; 144 } 145 146 /** 147 * Provides an object for performing assertions against the name of this header. 148 * 149 * @return An object for performing assertions against the name of this header. 150 */ 151 public FluentStringAssertion<BasicHeader> assertName() { 152 return new FluentStringAssertion<>(getName(), this); 153 } 154 155 /** 156 * Provides an object for performing assertions against the value of this header. 157 * 158 * @return An object for performing assertions against the value of this header. 159 */ 160 public FluentStringAssertion<BasicHeader> assertStringValue() { 161 return new FluentStringAssertion<>(getValue(), this); 162 } 163 164 /** 165 * Returns the value of this header as a string. 166 * 167 * @return The value of this header as a string, or {@link Optional#empty()} if the value is <jk>null</jk> 168 */ 169 public Optional<String> asString() { 170 return opt(getValue()); 171 } 172 173 @Override /* Overridden from Object */ 174 public boolean equals(Object o) { 175 // Functionality provided for HttpRequest.removeHeader(). 176 // Not a perfect equality operator if using SVL vars. 177 return o instanceof Header o2 && eq(this, o2, (x, y) -> eq(x.name, y.getName()) && eq(x.getValue(), y.getValue())); 178 } 179 180 /** 181 * Returns <jk>true</jk> if the specified value is the same using {@link String#equalsIgnoreCase(String)}. 182 * 183 * @param compare The value to compare against. 184 * @return <jk>true</jk> if the specified value is the same. 185 */ 186 public boolean equalsIgnoreCase(String compare) { 187 return eqic(getValue(), compare); 188 } 189 190 /** 191 * If a value is present, returns the value, otherwise throws {@link NoSuchElementException}. 192 * 193 * <p> 194 * This is a shortcut for calling <c>asString().get()</c>. 195 * 196 * @return The value if present. 197 */ 198 public String get() { 199 return asString().get(); 200 } 201 202 @Override 203 public HeaderElement[] getElements() throws ParseException { 204 if (elements == null) { 205 var s = getValue(); 206 HeaderElement[] x = s == null ? EMPTY_HEADER_ELEMENTS : BasicHeaderValueParser.parseElements(s, null); 207 if (supplier == null) 208 elements = x; 209 return x; 210 } 211 return elements; 212 } 213 214 @Override /* Overridden from Header */ 215 public String getName() { return name; } 216 217 @Override /* Overridden from Header */ 218 public String getValue() { 219 if (nn(supplier)) 220 return s(supplier.get()); 221 return stringValue; 222 } 223 224 @Override /* Overridden from Object */ 225 public int hashCode() { 226 // Implemented since we override equals(Object). 227 return super.hashCode(); 228 } 229 230 /** 231 * Returns <jk>true</jk> if the value exists and is not empty. 232 * 233 * <p> 234 * This is a shortcut for calling <c>!asString().orElse(<js>""</js>).isEmpty()</c>. 235 * 236 * @return <jk>true</jk> if the value exists and is not empty. 237 */ 238 public boolean isNotEmpty() { return ! asString().orElse("").isEmpty(); } 239 240 /** 241 * Returns <jk>true</jk> if the value exists. 242 * 243 * <p> 244 * This is a shortcut for calling <c>asString().isPresent()</c>. 245 * 246 * @return <jk>true</jk> if the value exists. 247 */ 248 public boolean isPresent() { return asString().isPresent(); } 249 250 /** 251 * If a value is present, returns the value, otherwise returns other. 252 * 253 * <p> 254 * This is a shortcut for calling <c>asString().orElse(<jv>other</jv>)</c>. 255 * 256 * @param other The other value. 257 * @return The value if present or the other value if not. 258 */ 259 public String orElse(String other) { 260 return asString().orElse(other); 261 } 262 263 @Override /* Overridden from Object */ 264 public String toString() { 265 return getName() + ": " + getValue(); 266 } 267}