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