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