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