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; 018 019import static org.apache.juneau.commons.utils.ThrowableUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.net.*; 023import java.time.*; 024import java.util.*; 025import java.util.function.*; 026 027import org.apache.http.*; 028import org.apache.juneau.*; 029import org.apache.juneau.http.header.*; 030import org.apache.juneau.http.part.*; 031import org.apache.juneau.httppart.*; 032import org.apache.juneau.commons.lang.*; 033import org.apache.juneau.commons.reflect.*; 034 035/** 036 * Standard predefined HTTP parts. 037 * 038 * <h5 class='section'>See Also:</h5><ul> 039 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a> 040 * </ul> 041 */ 042public class HttpParts { 043 044 private static final Function<ClassMeta<?>,String> HEADER_NAME_FUNCTION = x -> { 045 var n = Value.<String>empty(); 046 x.forEachAnnotation(org.apache.juneau.http.annotation.Header.class, y -> ne(y.value()), y -> n.set(y.value())); 047 x.forEachAnnotation(org.apache.juneau.http.annotation.Header.class, y -> ne(y.name()), y -> n.set(y.name())); 048 return n.orElse(null); 049 }; 050 051 private static final Function<ClassMeta<?>,String> QUERY_NAME_FUNCTION = x -> { 052 var n = Value.<String>empty(); 053 x.forEachAnnotation(org.apache.juneau.http.annotation.Query.class, y -> ne(y.value()), y -> n.set(y.value())); 054 x.forEachAnnotation(org.apache.juneau.http.annotation.Query.class, y -> ne(y.name()), y -> n.set(y.name())); 055 return n.orElse(null); 056 }; 057 058 private static final Function<ClassMeta<?>,String> FORMDATA_NAME_FUNCTION = x -> { 059 var n = Value.<String>empty(); 060 x.forEachAnnotation(org.apache.juneau.http.annotation.FormData.class, y -> ne(y.value()), y -> n.set(y.value())); 061 x.forEachAnnotation(org.apache.juneau.http.annotation.FormData.class, y -> ne(y.name()), y -> n.set(y.name())); 062 return n.orElse(null); 063 }; 064 065 private static final Function<ClassMeta<?>,String> PATH_NAME_FUNCTION = x -> { 066 var n = Value.<String>empty(); 067 x.forEachAnnotation(org.apache.juneau.http.annotation.Path.class, y -> ne(y.value()), y -> n.set(y.value())); 068 x.forEachAnnotation(org.apache.juneau.http.annotation.Path.class, y -> ne(y.name()), y -> n.set(y.name())); 069 return n.orElse(null); 070 }; 071 072 private static final Function<ClassMeta<?>,ConstructorInfo> CONSTRUCTOR_FUNCTION = x -> { 073 return x.getPublicConstructor(y -> y.hasParameterTypes(String.class)).orElseGet(() -> x.getPublicConstructor(y -> y.hasParameterTypes(String.class, String.class)).orElse(null)); 074 }; 075 076 /** 077 * Creates a {@link BasicPart} from a name/value pair string (e.g. <js>"Foo: bar"</js>) 078 * 079 * @param pair The pair string. 080 * @return A new {@link BasicPart} object. 081 */ 082 public static final BasicPart basicPart(String pair) { 083 return BasicPart.ofPair(pair); 084 } 085 086 /** 087 * Creates a new {@link BasicPart} part. 088 * 089 * @param name The part name. 090 * @param value The part value. 091 * @return A new {@link BasicPart} object. 092 */ 093 public static final BasicPart basicPart(String name, Object value) { 094 return BasicPart.of(name, value); 095 } 096 097 /** 098 * Creates a new {@link BasicPart} part with a delayed value. 099 * 100 * <p> 101 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 102 * 103 * @param name The part name. 104 * @param value The part value supplier. 105 * @return A new {@link BasicPart} object. 106 */ 107 public static final BasicPart basicPart(String name, Supplier<?> value) { 108 return BasicPart.of(name, value); 109 } 110 111 /** 112 * Creates a new {@link BasicBooleanPart} part. 113 * 114 * @param name The part name. 115 * @param value 116 * The part value. 117 * <br>Can be any of the following: 118 * <ul> 119 * <li>{@link Boolean} - As-is. 120 * <li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}. 121 * <li>Anything else - Converted to <c>String</c> and then parsed. 122 * </ul> 123 * @return A new {@link BasicBooleanPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 124 */ 125 public static final BasicBooleanPart booleanPart(String name, Boolean value) { 126 return BasicBooleanPart.of(name, value); 127 } 128 129 /** 130 * Creates a new {@link BasicBooleanPart} part with a delayed value. 131 * 132 * <p> 133 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 134 * 135 * @param name The part name. 136 * @param value 137 * The part value supplier. 138 * <br>Can be any of the following: 139 * <ul> 140 * <li>{@link Boolean} - As-is. 141 * <li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}. 142 * <li>Anything else - Converted to <c>String</c> and then parsed. 143 * </ul> 144 * @return A new {@link BasicBooleanPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 145 */ 146 public static final BasicBooleanPart booleanPart(String name, Supplier<Boolean> value) { 147 return BasicBooleanPart.of(name, value); 148 } 149 150 /** 151 * Returns <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object. 152 * 153 * @param o The object to check. 154 * @return <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object. 155 */ 156 public static boolean canCast(Object o) { 157 if (o == null) 158 return false; 159 var ci = ClassInfo.of(o); 160 return nn(ci) && ci.isChildOfAny(Headerable.class, NameValuePair.class, NameValuePairable.class, Map.Entry.class); 161 } 162 163 /** 164 * Utility method for converting an arbitrary object to a {@link NameValuePair}. 165 * 166 * @param o 167 * The object to cast or convert to a {@link NameValuePair}. 168 * @return Either the same object cast as a {@link NameValuePair} or converted to a {@link NameValuePair}. 169 */ 170 public static NameValuePair cast(Object o) { 171 if (o instanceof NameValuePair o2) 172 return o2; 173 if (o instanceof Headerable o3) { 174 Header x = o3.asHeader(); 175 return BasicPart.of(x.getName(), x.getValue()); 176 } 177 if (o instanceof Map.Entry o4) { 178 return BasicPart.of(s(o4.getKey()), o4.getValue()); 179 } 180 throw rex("Object of type {0} could not be converted to a Part.", cn(o)); 181 } 182 183 /** 184 * Creates a new {@link BasicCsvArrayPart} part. 185 * 186 * @param name The part name. 187 * @param value 188 * The part value. 189 * <br>Can be any of the following: 190 * <ul> 191 * <li><c>String</c> - A comma-delimited string. 192 * <li><c>String[]</c> - A pre-parsed value. 193 * <li>Any other array type - Converted to <c>String[]</c>. 194 * <li>Any {@link Collection} - Converted to <c>String[]</c>. 195 * <li>Anything else - Converted to <c>String</c>. 196 * </ul> 197 * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 198 */ 199 public static final BasicCsvArrayPart csvArrayPart(String name, String...value) { 200 return BasicCsvArrayPart.of(name, value); 201 } 202 203 /** 204 * Creates a new {@link BasicCsvArrayPart} part with a delayed value. 205 * 206 * <p> 207 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 208 * 209 * @param name The part name. 210 * @param value 211 * The part value supplier. 212 * <br>Can be any of the following: 213 * <ul> 214 * <li><c>String</c> - A comma-delimited string. 215 * <li><c>String[]</c> - A pre-parsed value. 216 * <li>Any other array type - Converted to <c>String[]</c>. 217 * <li>Any {@link Collection} - Converted to <c>String[]</c>. 218 * <li>Anything else - Converted to <c>String</c>. 219 * </ul> 220 * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 221 */ 222 public static final BasicCsvArrayPart csvArrayPart(String name, Supplier<String[]> value) { 223 return BasicCsvArrayPart.of(name, value); 224 } 225 226 /** 227 * Creates a new {@link BasicDatePart} part with a delayed value. 228 * 229 * <p> 230 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 231 * 232 * @param name The part name. 233 * @param value 234 * The part value supplier. 235 * <br>Can be any of the following: 236 * <ul> 237 * <li><c>String</c> - An ISO-8601 formated string (e.g. <js>"1994-10-29T19:43:31Z"</js>). 238 * <li>{@link ZonedDateTime} 239 * <li>{@link Calendar} 240 * <li>Anything else - Converted to <c>String</c>. 241 * </ul> 242 * @return A new {@link BasicDatePart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 243 */ 244 public static final BasicDatePart datePart(String name, Supplier<ZonedDateTime> value) { 245 return BasicDatePart.of(name, value); 246 } 247 248 /** 249 * Creates a new {@link BasicDatePart} part. 250 * 251 * @param name The part name. 252 * @param value 253 * The part value. 254 * <br>Can be any of the following: 255 * <ul> 256 * <li><c>String</c> - An ISO-8601 formated string (e.g. <js>"1994-10-29T19:43:31Z"</js>). 257 * <li>{@link ZonedDateTime} 258 * <li>{@link Calendar} 259 * <li>Anything else - Converted to <c>String</c>. 260 * </ul> 261 * @return A new {@link BasicDatePart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 262 */ 263 public static final BasicDatePart datePart(String name, ZonedDateTime value) { 264 return BasicDatePart.of(name, value); 265 } 266 267 /** 268 * Returns the constructor for the specified type. 269 * 270 * <p> 271 * Looks for one of the following constructors: 272 * <ul class='javatree'> 273 * <li class='jm><c><jk>public</jk> T(String <jv>value</jv>);</c> 274 * <li class='jm><c><jk>public</jk> T(String <jv>name</jv>, String <jv>value</jv>);</c> 275 * </ul> 276 * 277 * @param type The header type to find the constructor on. 278 * @return The constructor. Never <jk>null</jk>. 279 */ 280 public static Optional<ConstructorInfo> getConstructor(ClassMeta<?> type) { 281 return type.getProperty("HttpPart.Constructor", CONSTRUCTOR_FUNCTION); 282 } 283 284 /** 285 * Returns the name of the specified part type. 286 * 287 * <p> 288 * Gets the name from one of the following annotations: 289 * <ul class='javatreec'> 290 * <li class='ja'>{@link org.apache.juneau.http.annotation.Header} 291 * <li class='ja'>{@link org.apache.juneau.http.annotation.Query} 292 * <li class='ja'>{@link org.apache.juneau.http.annotation.FormData} 293 * <li class='ja'>{@link org.apache.juneau.http.annotation.Path} 294 * </ul> 295 * 296 * @param partType The part type. 297 * @param type The type to check. 298 * @return The part name. Never <jk>null</jk>. 299 */ 300 public static Optional<String> getName(HttpPartType partType, ClassMeta<?> type) { 301 return switch (partType) { 302 case FORMDATA -> type.getProperty("HttpPart.formData.name", FORMDATA_NAME_FUNCTION); 303 case HEADER -> type.getProperty("HttpPart.header.name", HEADER_NAME_FUNCTION); 304 case PATH -> type.getProperty("HttpPart.path.name", PATH_NAME_FUNCTION); 305 case QUERY -> type.getProperty("HttpPart.query.name", QUERY_NAME_FUNCTION); 306 default -> opte(); 307 }; 308 } 309 310 /** 311 * Creates a new {@link BasicIntegerPart} part. 312 * 313 * @param name The part name. 314 * @param value 315 * The part value. 316 * <br>Can be any of the following: 317 * <ul> 318 * <li>{@link Number} - Converted to an integer using {@link Number#intValue()}. 319 * <li>{@link String} - Parsed using {@link Integer#parseInt(String)}. 320 * <li>Anything else - Converted to <c>String</c>. 321 * </ul> 322 * @return A new {@link BasicIntegerPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 323 */ 324 public static final BasicIntegerPart integerPart(String name, Integer value) { 325 return BasicIntegerPart.of(name, value); 326 } 327 328 /** 329 * Creates a new {@link BasicIntegerPart} part with a delayed value. 330 * 331 * <p> 332 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 333 * 334 * @param name The part name. 335 * @param value 336 * The part value supplier. 337 * <br>Can be any of the following: 338 * <ul> 339 * <li>{@link Number} - Converted to an integer using {@link Number#intValue()}. 340 * <li>{@link String} - Parsed using {@link Integer#parseInt(String)}. 341 * <li>Anything else - Converted to <c>String</c>. 342 * </ul> 343 * @return A new {@link BasicIntegerPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 344 */ 345 public static final BasicIntegerPart integerPart(String name, Supplier<Integer> value) { 346 return BasicIntegerPart.of(name, value); 347 } 348 349 /** 350 * Returns <jk>true</jk> if the specified type is a part type. 351 * 352 * <p> 353 * A part type extends from either {@link org.apache.http.Header} or {@link org.apache.http.NameValuePair} 354 * or is annotated with {@link org.apache.juneau.http.annotation.Header}, {@link org.apache.juneau.http.annotation.Query}, 355 * {@link org.apache.juneau.http.annotation.FormData}, or {@link org.apache.juneau.http.annotation.Path}. 356 * 357 * @param partType The part type. 358 * @param type The type to check. 359 * @return <jk>true</jk> if the specified type is a part type. 360 */ 361 public static boolean isHttpPart(HttpPartType partType, ClassMeta<?> type) { 362 return switch (partType) { 363 case PATH, QUERY, FORMDATA -> type.getProperty("HttpPart.isNameValuePair", x -> x.isChildOf(NameValuePair.class)).orElse(false); 364 case HEADER -> type.getProperty("HttpPart.isHeader", x -> x.isChildOf(org.apache.http.Header.class)).orElse(false); 365 default -> false; 366 }; 367 } 368 369 /** 370 * Creates a new {@link BasicLongPart} part. 371 * 372 * @param name The part name. 373 * @param value 374 * The part value. 375 * <br>Can be any of the following: 376 * <ul> 377 * <li>{@link Number} - Converted to a long using {@link Number#longValue()}. 378 * <li>{@link String} - Parsed using {@link Long#parseLong(String)}. 379 * <li>Anything else - Converted to <c>String</c>. 380 * </ul> 381 * @return A new {@link BasicLongPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 382 */ 383 public static final BasicLongPart longPart(String name, Long value) { 384 return BasicLongPart.of(name, value); 385 } 386 387 /** 388 * Creates a new {@link BasicLongPart} part with a delayed value. 389 * 390 * <p> 391 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 392 * 393 * @param name The part name. 394 * @param value 395 * The part value supplier. 396 * <br>Can be any of the following: 397 * <ul> 398 * <li>{@link Number} - Converted to a long using {@link Number#longValue()}. 399 * <li>{@link String} - Parsed using {@link Long#parseLong(String)}. 400 * <li>Anything else - Converted to <c>String</c>. 401 * </ul> 402 * @return A new {@link BasicLongPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 403 */ 404 public static final BasicLongPart longPart(String name, Supplier<Long> value) { 405 return BasicLongPart.of(name, value); 406 } 407 408 /** 409 * Instantiates a new {@link org.apache.juneau.http.part.PartList}. 410 * 411 * @return A new part list. 412 */ 413 public static final PartList partList() { 414 return PartList.create(); 415 } 416 417 /** 418 * Creates a new {@link PartList} initialized with the specified parts. 419 * 420 * @param parts The parts to add to the list. Can be <jk>null</jk>. <jk>null</jk> entries are ignored. 421 * @return A new unmodifiable instance, never <jk>null</jk>. 422 */ 423 public static final PartList partList(List<NameValuePair> parts) { 424 return PartList.of(parts); 425 } 426 427 /** 428 * Creates a new {@link PartList} initialized with the specified parts. 429 * 430 * @param parts The parts to add to the list. <jk>null</jk> entries are ignored. 431 * @return A new unmodifiable instance, never <jk>null</jk>. 432 */ 433 public static final PartList partList(NameValuePair...parts) { 434 return PartList.of(parts); 435 } 436 437 /** 438 * Creates a new {@link PartList} initialized with the specified name/value pairs. 439 * 440 * @param pairs 441 * Initial list of pairs. 442 * <br>Must be an even number of parameters representing key/value pairs. 443 * @throws RuntimeException If odd number of parameters were specified. 444 * @return A new instance. 445 */ 446 public static PartList partList(String...pairs) { 447 return PartList.ofPairs(pairs); 448 } 449 450 /** 451 * Creates a new {@link SerializedPart} part. 452 * 453 * @param name The part name. 454 * @param value 455 * The part value. 456 * <br>Can be any POJO. 457 * @return A new {@link SerializedPart} object, never <jk>null</jk>. 458 */ 459 public static final SerializedPart serializedPart(String name, Object value) { 460 return SerializedPart.of(name, value); 461 } 462 463 /** 464 * Creates a new {@link SerializedPart} part with a delayed value. 465 * 466 * @param name The part name. 467 * @param value 468 * The part value supplier. 469 * <br>Can be a supplier of any POJO. 470 * @return A new {@link SerializedPart} object, never <jk>null</jk>. 471 */ 472 public static final SerializedPart serializedPart(String name, Supplier<?> value) { 473 return SerializedPart.of(name, value); 474 } 475 476 /** 477 * Creates a new {@link BasicStringPart} part. 478 * 479 * @param name The part name. 480 * @param value 481 * The part value. 482 * <br>Can be any of the following: 483 * <ul> 484 * <li>{@link String} 485 * <li>Anything else - Converted to <c>String</c> then parsed. 486 * </ul> 487 * @return A new {@link BasicStringPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 488 */ 489 public static final BasicStringPart stringPart(String name, String value) { 490 return BasicStringPart.of(name, value); 491 } 492 493 /** 494 * Creates a new {@link BasicStringPart} part with a delayed value. 495 * 496 * <p> 497 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 498 * 499 * @param name The part name. 500 * @param value 501 * The part value supplier. 502 * <br>Can be any of the following: 503 * <ul> 504 * <li>{@link String} 505 * <li>Anything else - Converted to <c>String</c> then parsed. 506 * </ul> 507 * @return A new {@link BasicStringPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 508 */ 509 public static final BasicStringPart stringPart(String name, Supplier<String> value) { 510 return BasicStringPart.of(name, value); 511 } 512 513 /** 514 * Creates a new {@link BasicUriPart} part with a delayed value. 515 * 516 * <p> 517 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}. 518 * 519 * @param name The header name. 520 * @param value 521 * The header value supplier. 522 * <br>Can be any of the following: 523 * <ul> 524 * <li>{@link String} 525 * <li>Anything else - Converted to <c>String</c> then parsed. 526 * </ul> 527 * @return A new {@link BasicUriPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 528 */ 529 public static final BasicUriPart uriPart(String name, Supplier<URI> value) { 530 return BasicUriPart.of(name, value); 531 } 532 533 /** 534 * Creates a new {@link BasicUriPart} part. 535 * 536 * @param name The header name. 537 * @param value 538 * The header value. 539 * <br>Can be any of the following: 540 * <ul> 541 * <li>{@link String} 542 * <li>Anything else - Converted to <c>String</c> then parsed. 543 * </ul> 544 * @return A new {@link BasicUriPart} object, or <jk>null</jk> if the name or value is <jk>null</jk>. 545 */ 546 public static final BasicUriPart uriPart(String name, URI value) { 547 return BasicUriPart.of(name, value); 548 } 549}