001/* 002 * Copyright 2020-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2020-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2020-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk; 037 038 039 040import java.io.Serializable; 041import java.util.Collections; 042import java.util.Iterator; 043import java.util.LinkedHashMap; 044import java.util.Map; 045 046import com.unboundid.util.Mutable; 047import com.unboundid.util.NotNull; 048import com.unboundid.util.Nullable; 049import com.unboundid.util.ThreadSafety; 050import com.unboundid.util.ThreadSafetyLevel; 051import com.unboundid.util.Validator; 052 053 054 055/** 056 * This class provides a data structure that may be used to hold a number of 057 * properties used during processing for a OAUTHBEARER SASL bind operation. 058 * 059 * @see OAUTHBEARERBindRequest 060 */ 061@Mutable() 062@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 063public final class OAUTHBEARERBindRequestProperties 064 implements Serializable 065{ 066 /** 067 * The serial version UID for this serializable class. 068 */ 069 private static final long serialVersionUID = -7664683436256231975L; 070 071 072 073 // The port of the server to which the request will be sent. 074 @Nullable private Integer serverPort; 075 076 // A set of additional key-value pairs that should be included in the bind 077 // request. 078 @NotNull private final Map<String,String> additionalKeyValuePairs; 079 080 // The access token to include in the bind request. 081 @NotNull private String accessToken; 082 083 // The authorization identity to include in the GS2 header for the bind 084 // request. 085 @Nullable private String authorizationID; 086 087 // The method to use for HTTP-based requests. 088 @Nullable private String requestMethod; 089 090 // The path to use for HTTP-based requests. 091 @Nullable private String requestPath; 092 093 // The post data for HTTP-based requests. 094 @Nullable private String requestPostData; 095 096 // The query string for HTTP-based requests. 097 @Nullable private String requestQueryString; 098 099 // The address of the server to which the request will be sent. 100 @Nullable private String serverAddress; 101 102 103 104 /** 105 * Creates a new set of OAUTHBEARER bind request properties with the provided 106 * access token. 107 * 108 * @param accessToken The access token to include in the bind request. It 109 * must not be {@code null} or empty. 110 */ 111 public OAUTHBEARERBindRequestProperties(@NotNull final String accessToken) 112 { 113 Validator.ensureNotNullOrEmpty(accessToken, 114 "OAUTHBEARERBindRequestProperties.accessToken must not be null or " + 115 "empty."); 116 117 this.accessToken = accessToken; 118 119 authorizationID = null; 120 serverAddress = null; 121 serverPort = null; 122 requestMethod = null; 123 requestPath = null; 124 requestPostData = null; 125 requestQueryString = null; 126 127 additionalKeyValuePairs = new LinkedHashMap<>(); 128 } 129 130 131 132 /** 133 * Creates a new set of OAUTHBEARER bind request properties that is a copy of 134 * the provided set of properties. 135 * 136 * @param properties The set of properties to duplicate. It must not be 137 * {@code null}. 138 */ 139 public OAUTHBEARERBindRequestProperties( 140 @NotNull final OAUTHBEARERBindRequestProperties properties) 141 { 142 Validator.ensureNotNullWithMessage(properties, 143 "OAUTHBEARERBindRequestProperties.properties must not be null."); 144 145 accessToken = properties.accessToken; 146 authorizationID = properties.authorizationID; 147 serverAddress = properties.serverAddress; 148 serverPort = properties.serverPort; 149 requestMethod = properties.requestMethod; 150 requestPath = properties.requestPath; 151 requestPostData = properties.requestPostData; 152 requestQueryString = properties.requestQueryString; 153 additionalKeyValuePairs = 154 new LinkedHashMap<>(properties.additionalKeyValuePairs); 155 } 156 157 158 159 /** 160 * Creates a new set of OAUTHBEARER bind request properties that is a copy of 161 * the properties used for the provided bind request. 162 * 163 * @param bindRequest The OAUTHBEARER bind request to use to create this set 164 * of properties. It must not be {@code null}. 165 */ 166 public OAUTHBEARERBindRequestProperties( 167 @NotNull final OAUTHBEARERBindRequest bindRequest) 168 { 169 Validator.ensureNotNullWithMessage(bindRequest, 170 "OAUTHBEARERBindRequestProperties.bindRequest must not be null."); 171 172 accessToken = bindRequest.getAccessToken(); 173 authorizationID = bindRequest.getAuthorizationID(); 174 serverAddress = bindRequest.getServerAddress(); 175 serverPort = bindRequest.getServerPort(); 176 requestMethod = bindRequest.getRequestMethod(); 177 requestPath = bindRequest.getRequestPath(); 178 requestPostData = bindRequest.getRequestPostData(); 179 requestQueryString = bindRequest.getRequestQueryString(); 180 additionalKeyValuePairs = 181 new LinkedHashMap<>(bindRequest.getAdditionalKeyValuePairs()); 182 } 183 184 185 186 /** 187 * Retrieves the access token to include in the bind request. 188 * 189 * @return The access token to include in the bind request. 190 */ 191 @NotNull() 192 public String getAccessToken() 193 { 194 return accessToken; 195 } 196 197 198 199 /** 200 * Specifies the access token to include in the bind request. 201 * 202 * @param accessToken The access token to include in the bind request. It 203 * must not be {@code null} or empty. 204 */ 205 public void setAccessToken(@NotNull final String accessToken) 206 { 207 Validator.ensureNotNullOrEmpty(accessToken, 208 "OAUTHBEARERBindRequestProperties.accessToken must not be null or " + 209 "empty."); 210 211 this.accessToken = accessToken; 212 } 213 214 215 216 /** 217 * Retrieves the authorization ID to include in the GS2 header for the bind 218 * request, if any. 219 * 220 * @return The authorization ID to include in the GS2 header for the bind 221 * request, or {@code null} if no authorization ID should be 222 * included. 223 */ 224 @Nullable() 225 public String getAuthorizationID() 226 { 227 return authorizationID; 228 } 229 230 231 232 /** 233 * Specifies the authorization ID to include in the GS2 header for the bind 234 * request, if any. 235 * 236 * @param authorizationID The authorization ID to include in the bind 237 * request. It may be {@code null} if no 238 * authorization ID should be provided. 239 */ 240 public void setAuthorizationID(@Nullable final String authorizationID) 241 { 242 this.authorizationID = authorizationID; 243 } 244 245 246 247 /** 248 * Retrieves the server address to include in the bind request, if any. 249 * 250 * @return The server address to include in the bind request, or {@code null} 251 * if it should be omitted. 252 */ 253 @Nullable() 254 public String getServerAddress() 255 { 256 return serverAddress; 257 } 258 259 260 261 /** 262 * Specifies the server address to include in the bind request, if any. 263 * 264 * @param serverAddress The server address to include in the bind request. 265 * It may be {@code null} if the server address should 266 * be omitted. 267 */ 268 public void setServerAddress(@Nullable final String serverAddress) 269 { 270 this.serverAddress = serverAddress; 271 } 272 273 274 275 /** 276 * Retrieves the server port to include in the bind request, if any. 277 * 278 * @return The server port to include in the bind request, or {@code null} 279 * if it should be omitted. 280 */ 281 @Nullable() 282 public Integer getServerPort() 283 { 284 return serverPort; 285 } 286 287 288 289 /** 290 * Specifies the server port to include in the bind request, if any. 291 * 292 * @param serverPort The server port to include in the bind request. It 293 * may be {@code null} if the server port should be 294 * omitted. If it is non-{@code null}, then the value 295 * must be between 1 and 65535, inclusive. 296 */ 297 public void setServerPort(@Nullable final Integer serverPort) 298 { 299 if (serverPort != null) 300 { 301 Validator.ensureTrue(((serverPort >= 1) && (serverPort <= 65535)), 302 "If provided, OAUTHBEARERBindRequestProperties.serverPort must be " + 303 "between 1 and 65535, inclusive."); 304 } 305 306 this.serverPort = serverPort; 307 } 308 309 310 311 /** 312 * Retrieves the method to use for HTTP-based requests, if any. 313 * 314 * @return The method to use for HTTP-based requests, or {@code null} if it 315 * should be omitted from the bind request. 316 */ 317 @Nullable() 318 public String getRequestMethod() 319 { 320 return requestMethod; 321 } 322 323 324 325 /** 326 * Specifies the method to use for HTTP-based requests, if it should be 327 * included in the bind request. 328 * 329 * @param requestMethod The method to use for HTTP-based requests. It may 330 * be {@code null} if the request method should be 331 * omitted. 332 */ 333 public void setRequestMethod(@Nullable final String requestMethod) 334 { 335 this.requestMethod = requestMethod; 336 } 337 338 339 340 /** 341 * Retrieves the path to use for HTTP-based requests, if any. 342 * 343 * @return The path to use for HTTP-based requests, or {@code null} if it 344 * should be omitted from the bind request. 345 */ 346 @Nullable() 347 public String getRequestPath() 348 { 349 return requestPath; 350 } 351 352 353 354 /** 355 * Specifies the path to use for HTTP-based requests, if it should be included 356 * in the bind request. 357 * 358 * @param requestPath The path to use for HTTP-based requests. It may be 359 * {@code null} if the request path should be omitted. 360 */ 361 public void setRequestPath(@Nullable final String requestPath) 362 { 363 this.requestPath = requestPath; 364 } 365 366 367 368 /** 369 * Retrieves the data to submit when posting an HTTP-based request, if any. 370 * 371 * @return The post data for HTTP-based requests, or {@code null} if it 372 * should be omitted from the bind request. 373 */ 374 @Nullable() 375 public String getRequestPostData() 376 { 377 return requestPostData; 378 } 379 380 381 382 /** 383 * Specifies the data to submit when posting an HTTP-based request, if it 384 * should be included in the bind request. 385 * 386 * @param requestPostData The post data for HTTP-based requests. It may be 387 * {@code null} if the post data should be omitted. 388 */ 389 public void setRequestPostData(@Nullable final String requestPostData) 390 { 391 this.requestPostData = requestPostData; 392 } 393 394 395 396 /** 397 * Retrieves the query string to use for HTTP-based requests, if any. 398 * 399 * @return The query string to use for HTTP-based requests, or {@code null} 400 * if it should be omitted from the bind request. 401 */ 402 @Nullable() 403 public String getRequestQueryString() 404 { 405 return requestQueryString; 406 } 407 408 409 410 /** 411 * Specifies the query string to use for HTTP-based requests, if it should be 412 * included in the bind request. 413 * 414 * @param requestQueryString The query string to use for HTTP-based 415 * requests. It may be {@code null} if it should 416 * be omitted from the bind request. 417 */ 418 public void setRequestQueryString(@Nullable final String requestQueryString) 419 { 420 this.requestQueryString = requestQueryString; 421 } 422 423 424 425 /** 426 * Retrieves an unmodifiable map of additional key-value pairs that should be 427 * included in the bind request. 428 * 429 * @return An unmodifiable map of additional key-value pairs that should be 430 * included in the bind request. 431 */ 432 @NotNull() 433 public Map<String,String> getAdditionalKeyValuePairs() 434 { 435 return Collections.unmodifiableMap(additionalKeyValuePairs); 436 } 437 438 439 440 /** 441 * Adds an item to the set of additional key-value pairs that should be 442 * included in the bind request. If an item is already defined with the 443 * provided key, then its value will be replaced. 444 * 445 * @param key The key to use. It must not be {@code null} or empty, and 446 * it must contain only alphabetic characters. 447 * @param value The value to use for the key. It must not be {@code null}, 448 * and it must not contain the 0x00 or 0x01 characters. 449 */ 450 public void addKeyValuePair(@NotNull final String key, 451 @NotNull final String value) 452 { 453 Validator.ensureNotNullOrEmpty(key, 454 "OAUTHBEARERBindRequestProperties.addKeyValuePair.key must not be " + 455 "null or empty."); 456 for (final char c : key.toCharArray()) 457 { 458 Validator.ensureTrue( 459 (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))), 460 "OAUTHBEARERBindRequestProperties.addKeyValuePair.key must " + 461 "contain only alphabetic characters."); 462 } 463 464 Validator.ensureNotNull(value, 465 "OAUTHBEARERBindRequestProperties.addKeyValuePair.value must not be " + 466 "null."); 467 for (final char c : value.toCharArray()) 468 { 469 Validator.ensureFalse( 470 ((c == '\u0000') || (c == '\u0001')), 471 "OAUTHBEARERBindRequestProperties.addKeyValuePair.value must not " + 472 "contain the characters \\u0000 or \\u0001."); 473 } 474 475 additionalKeyValuePairs.put(key, value); 476 } 477 478 479 480 /** 481 * Removes the specified additional key-value pair so it will not be included 482 * in the bind request. 483 * 484 * @param key The key to remove. 485 * 486 * @return The value that was associated with the key. It may be 487 * {@code null} if the specified key was not set. 488 */ 489 @Nullable() 490 public String removeKeyValuePair(@NotNull final String key) 491 { 492 return additionalKeyValuePairs.remove(key); 493 } 494 495 496 497 /** 498 * Clears the set of additional key-value pairs. 499 */ 500 public void clearAdditionalKeyValuePairs() 501 { 502 additionalKeyValuePairs.clear(); 503 } 504 505 506 507 /** 508 * Retrieves a string representation of the OAUTHBEARER bind request 509 * properties. 510 * 511 * @return A string representation of the OAUTHBEARER bind request 512 * properties. 513 */ 514 @Override() 515 @NotNull() 516 public String toString() 517 { 518 final StringBuilder buffer = new StringBuilder(); 519 toString(buffer); 520 return buffer.toString(); 521 } 522 523 524 525 /** 526 * Appends a string representation of the OAUTHBEARER bind request properties 527 * to the provided buffer. 528 * 529 * @param buffer The buffer to which the information should be appended. It 530 * must not be {@code null}. 531 */ 532 public void toString(@NotNull final StringBuilder buffer) 533 { 534 buffer.append("OAUTHBEARERBindRequestProperties(accessToken='{redacted}'"); 535 536 if (authorizationID != null) 537 { 538 buffer.append(", authorizationID='"); 539 buffer.append(authorizationID); 540 buffer.append('\''); 541 } 542 543 if (serverAddress != null) 544 { 545 buffer.append(", serverAddress='"); 546 buffer.append(serverAddress); 547 buffer.append('\''); 548 } 549 550 if (serverPort != null) 551 { 552 buffer.append(", serverPort="); 553 buffer.append(serverPort); 554 } 555 556 if (requestMethod != null) 557 { 558 buffer.append(", requestMethod='"); 559 buffer.append(requestMethod); 560 buffer.append('\''); 561 } 562 563 if (requestPath != null) 564 { 565 buffer.append(", requestPath='"); 566 buffer.append(requestPath); 567 buffer.append('\''); 568 } 569 570 if (requestPostData != null) 571 { 572 buffer.append(", requestPostData='{redacted}'"); 573 } 574 575 if (requestQueryString != null) 576 { 577 buffer.append(", requestQueryString='"); 578 buffer.append(requestQueryString); 579 buffer.append('\''); 580 } 581 582 if (! additionalKeyValuePairs.isEmpty()) 583 { 584 buffer.append(", additionalKeyValuePairs=["); 585 586 final Iterator<Map.Entry<String,String>> iterator = 587 additionalKeyValuePairs.entrySet().iterator(); 588 while (iterator.hasNext()) 589 { 590 final Map.Entry<String,String> e = iterator.next(); 591 buffer.append(" \""); 592 buffer.append(e.getKey()); 593 buffer.append("\"=\""); 594 buffer.append(e.getValue()); 595 buffer.append('"'); 596 597 if (iterator.hasNext()) 598 { 599 buffer.append(','); 600 } 601 } 602 603 buffer.append(" ]"); 604 } 605 606 buffer.append(')'); 607 } 608}