001 /*
002 * Copyright 2007-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2014 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 */
021 package com.unboundid.ldap.sdk;
022
023
024
025 import java.util.List;
026
027 import com.unboundid.util.NotExtensible;
028 import com.unboundid.util.ThreadSafety;
029 import com.unboundid.util.ThreadSafetyLevel;
030
031 import 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)
044 public 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 }