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