001/* 002 * Copyright 2007-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2007-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) 2007-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.util.List; 041 042import com.unboundid.util.NotExtensible; 043import com.unboundid.util.NotNull; 044import com.unboundid.util.Nullable; 045import com.unboundid.util.ThreadSafety; 046import com.unboundid.util.ThreadSafetyLevel; 047import com.unboundid.util.Validator; 048 049 050 051/** 052 * This class is the superclass of all types of LDAP requests that can be 053 * altered. It provides methods for updating the set of controls to include as 054 * part of the request and for configuring a response timeout, which is 055 * the maximum length of time that the SDK should wait for a response to the 056 * request before returning an error back to the caller. 057 */ 058@NotExtensible() 059@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 060public abstract class UpdatableLDAPRequest 061 extends LDAPRequest 062{ 063 /** 064 * The serial version UID for this serializable class. 065 */ 066 private static final long serialVersionUID = 2487230102594573848L; 067 068 069 070 /** 071 * Creates a new LDAP request with the provided set of controls. 072 * 073 * @param controls The set of controls to include in this LDAP request. 074 */ 075 protected UpdatableLDAPRequest(@Nullable final Control[] controls) 076 { 077 super(controls); 078 } 079 080 081 082 /** 083 * Specifies the set of controls for this request. 084 * 085 * @param controls The set of controls for this request. 086 */ 087 public final void setControls(@Nullable final Control... controls) 088 { 089 if (controls == null) 090 { 091 setControlsInternal(NO_CONTROLS); 092 } 093 else 094 { 095 setControlsInternal(controls); 096 } 097 } 098 099 100 101 /** 102 * Specifies the set of controls for this request. 103 * 104 * @param controls The set of controls for this request. 105 */ 106 public final void setControls(@Nullable final List<Control> controls) 107 { 108 if ((controls == null) || controls.isEmpty()) 109 { 110 setControlsInternal(NO_CONTROLS); 111 } 112 else 113 { 114 final Control[] controlArray = new Control[controls.size()]; 115 setControlsInternal(controls.toArray(controlArray)); 116 } 117 } 118 119 120 121 /** 122 * Removes all controls from this request. 123 */ 124 public final void clearControls() 125 { 126 setControlsInternal(NO_CONTROLS); 127 } 128 129 130 131 /** 132 * Adds the provided control to the set of controls for this request. 133 * 134 * @param control The control to add to the set of controls for this 135 * request. It must not be {@code null}. 136 */ 137 public final void addControl(@NotNull final Control control) 138 { 139 Validator.ensureNotNull(control); 140 141 final Control[] controls = getControls(); 142 143 final Control[] newControls = new Control[controls.length+1]; 144 System.arraycopy(controls, 0, newControls, 0, controls.length); 145 newControls[controls.length] = control; 146 147 setControlsInternal(newControls); 148 } 149 150 151 152 /** 153 * Adds the provided controls to the set of controls for this request. 154 * 155 * @param controls The controls to add to the set of controls for this 156 * request. 157 */ 158 public final void addControls(@Nullable final Control... controls) 159 { 160 if ((controls == null) || (controls.length == 0)) 161 { 162 return; 163 } 164 165 final Control[] currentControls = getControls(); 166 167 final Control[] newControls = 168 new Control[currentControls.length + controls.length]; 169 System.arraycopy(currentControls, 0, newControls, 0, 170 currentControls.length); 171 System.arraycopy(controls, 0, newControls, currentControls.length, 172 controls.length); 173 174 setControlsInternal(newControls); 175 } 176 177 178 179 /** 180 * Removes the control with the specified OID from the set of controls for 181 * this request. If this request has multiple controls with the same OID, 182 * then only the first will be removed. 183 * 184 * @param oid The OID of the control to remove. It must not be 185 * {@code null}. 186 * 187 * @return The control that was removed, or {@code null} if this request does 188 * not have any control with the specified OID. 189 */ 190 @Nullable() 191 public final Control removeControl(@NotNull final String oid) 192 { 193 Validator.ensureNotNull(oid); 194 195 final Control[] controls = getControls(); 196 197 int pos = -1; 198 Control c = null; 199 for (int i=0; i < controls.length; i++) 200 { 201 if (controls[i].getOID().equals(oid)) 202 { 203 c = controls[i]; 204 pos = i; 205 break; 206 } 207 } 208 209 if (pos < 0) 210 { 211 return null; 212 } 213 214 if (controls.length == 1) 215 { 216 setControlsInternal(NO_CONTROLS); 217 } 218 else 219 { 220 final Control[] newControls = new Control[controls.length - 1]; 221 for (int i=0,j=0; i < controls.length; i++) 222 { 223 if (i != pos) 224 { 225 newControls[j++] = controls[i]; 226 } 227 } 228 setControlsInternal(newControls); 229 } 230 231 return c; 232 } 233 234 235 236 /** 237 * Removes the provided control from the set of controls for this request. 238 * This will have no impact if the provided control is not included in the set 239 * of controls for this request. 240 * 241 * @param control The control to remove from the set of controls for this 242 * request. It must not be {@code null}. 243 * 244 * @return {@code true} if the control was found and removed, or 245 * {@code false} if not. 246 */ 247 public final boolean removeControl(@NotNull final Control control) 248 { 249 Validator.ensureNotNull(control); 250 251 final Control[] controls = getControls(); 252 253 int pos = -1; 254 for (int i=0; i < controls.length; i++) 255 { 256 if (controls[i].equals(control)) 257 { 258 pos = i; 259 break; 260 } 261 } 262 263 if (pos < 0) 264 { 265 return false; 266 } 267 268 if (controls.length == 1) 269 { 270 setControlsInternal(NO_CONTROLS); 271 } 272 else 273 { 274 final Control[] newControls = new Control[controls.length - 1]; 275 for (int i=0,j=0; i < controls.length; i++) 276 { 277 if (i != pos) 278 { 279 newControls[j++] = controls[i]; 280 } 281 } 282 setControlsInternal(newControls); 283 } 284 285 return true; 286 } 287 288 289 290 /** 291 * Replaces the control with the same OID as the provided control with the 292 * provided control. If no control with the same OID exists in the request, 293 * then the control will be added to the request. If the request has multiple 294 * controls with the same OID as the new control, then only the first will be 295 * replaced. 296 * 297 * @param control The control to use in place of the existing control with 298 * the same OID. It must not be {@code null}. 299 * 300 * @return The control that was replaced, or {@code null} if there was no 301 * control with the same OID as the provided control. 302 */ 303 @Nullable() 304 public final Control replaceControl(@NotNull final Control control) 305 { 306 Validator.ensureNotNull(control); 307 308 return replaceControl(control.getOID(), control); 309 } 310 311 312 313 /** 314 * Replaces the control with the specified OID with the provided control. If 315 * no control with the given OID exists in the request, then a new control 316 * will be added. If this request has multiple controls with the specified 317 * OID, then only the first will be replaced. 318 * 319 * @param oid The OID of the control to replace with the provided 320 * control. It must not be {@code null}. 321 * @param control The control to use in place of the control with the 322 * specified OID. It may be {@code null} if the control 323 * should be removed. It may have a different OID than the 324 * OID of the control being replaced. 325 * 326 * @return The control that was replaced, or {@code null} if there was no 327 * control with the specified OID. 328 */ 329 @Nullable() 330 public final Control replaceControl(@NotNull final String oid, 331 @Nullable final Control control) 332 { 333 Validator.ensureNotNull(oid); 334 335 if (control == null) 336 { 337 return removeControl(oid); 338 } 339 340 final Control[] controls = getControls(); 341 for (int i=0; i < controls.length; i++) 342 { 343 if (controls[i].getOID().equals(oid)) 344 { 345 final Control c = controls[i]; 346 controls[i] = control; 347 setControlsInternal(controls); 348 return c; 349 } 350 } 351 352 final Control[] newControls = new Control[controls.length+1]; 353 System.arraycopy(controls, 0, newControls, 0, controls.length); 354 newControls[controls.length] = control; 355 setControlsInternal(newControls); 356 return null; 357 } 358}