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