001    /*
002     * Copyright 2009-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2016 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.protocol;
022    
023    
024    
025    import java.util.ArrayList;
026    import java.util.Collections;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    import com.unboundid.asn1.ASN1Buffer;
031    import com.unboundid.asn1.ASN1BufferSequence;
032    import com.unboundid.asn1.ASN1Element;
033    import com.unboundid.asn1.ASN1OctetString;
034    import com.unboundid.asn1.ASN1Sequence;
035    import com.unboundid.asn1.ASN1StreamReader;
036    import com.unboundid.asn1.ASN1StreamReaderSequence;
037    import com.unboundid.ldap.sdk.Control;
038    import com.unboundid.ldap.sdk.LDAPException;
039    import com.unboundid.ldap.sdk.ResultCode;
040    import com.unboundid.ldap.sdk.SearchResultReference;
041    import com.unboundid.util.InternalUseOnly;
042    
043    import static com.unboundid.ldap.protocol.ProtocolMessages.*;
044    import static com.unboundid.util.Debug.*;
045    import static com.unboundid.util.StaticUtils.*;
046    
047    
048    
049    /**
050     * This class provides an implementation of an LDAP search result reference
051     * protocol op.
052     */
053    @InternalUseOnly()
054    public final class SearchResultReferenceProtocolOp
055           implements ProtocolOp
056    {
057      /**
058       * The serial version UID for this serializable class.
059       */
060      private static final long serialVersionUID = -1526778443581862609L;
061    
062    
063    
064      // The list of referral URLs for this search result reference.
065      private final List<String> referralURLs;
066    
067    
068    
069      /**
070       * Creates a new search result reference protocol op with the provided
071       * information.
072       *
073       * @param  referralURLs  The list of referral URLs for this search result
074       *                       reference.
075       */
076      public SearchResultReferenceProtocolOp(final List<String> referralURLs)
077      {
078        this.referralURLs = Collections.unmodifiableList(referralURLs);
079      }
080    
081    
082    
083      /**
084       * Creates a new search result reference protocol op from the provided search
085       * result reference.
086       *
087       * @param  reference  The search result reference to use to create this
088       *                    protocol op.
089       */
090      public SearchResultReferenceProtocolOp(final SearchResultReference reference)
091      {
092        referralURLs = toList(reference.getReferralURLs());
093      }
094    
095    
096    
097      /**
098       * Creates a new search result reference protocol op read from the provided
099       * ASN.1 stream reader.
100       *
101       * @param  reader  The ASN.1 stream reader from which to read the search
102       *                 result reference protocol op.
103       *
104       * @throws  LDAPException  If a problem occurs while reading or parsing the
105       *                         search result reference.
106       */
107      SearchResultReferenceProtocolOp(final ASN1StreamReader reader)
108           throws LDAPException
109      {
110        try
111        {
112          final ArrayList<String> refs = new ArrayList<String>(5);
113          final ASN1StreamReaderSequence refSequence = reader.beginSequence();
114          while (refSequence.hasMoreElements())
115          {
116            refs.add(reader.readString());
117          }
118    
119          referralURLs = Collections.unmodifiableList(refs);
120        }
121        catch (Exception e)
122        {
123          debugException(e);
124    
125          throw new LDAPException(ResultCode.DECODING_ERROR,
126               ERR_SEARCH_REFERENCE_CANNOT_DECODE.get(getExceptionMessage(e)), e);
127        }
128      }
129    
130    
131    
132      /**
133       * Retrieves the list of referral URLs for this search result reference.
134       *
135       * @return  The list of referral URLs for this search result reference.
136       */
137      public List<String> getReferralURLs()
138      {
139        return referralURLs;
140      }
141    
142    
143    
144      /**
145       * {@inheritDoc}
146       */
147      public byte getProtocolOpType()
148      {
149        return LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_RESULT_REFERENCE;
150      }
151    
152    
153    
154      /**
155       * {@inheritDoc}
156       */
157      public ASN1Element encodeProtocolOp()
158      {
159        final ArrayList<ASN1Element> urlElements =
160             new ArrayList<ASN1Element>(referralURLs.size());
161        for (final String url : referralURLs)
162        {
163          urlElements.add(new ASN1OctetString(url));
164        }
165    
166        return new ASN1Sequence(
167             LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_RESULT_REFERENCE,
168             urlElements);
169      }
170    
171    
172    
173      /**
174       * Decodes the provided ASN.1 element as a search result reference protocol
175       * op.
176       *
177       * @param  element  The ASN.1 element to be decoded.
178       *
179       * @return  The decoded search result reference protocol op.
180       *
181       * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
182       *                         a search result reference protocol op.
183       */
184      public static SearchResultReferenceProtocolOp decodeProtocolOp(
185                                                         final ASN1Element element)
186             throws LDAPException
187      {
188        try
189        {
190          final ASN1Element[] urlElements =
191               ASN1Sequence.decodeAsSequence(element).elements();
192          final ArrayList<String> referralURLs =
193               new ArrayList<String>(urlElements.length);
194          for (final ASN1Element e : urlElements)
195          {
196            referralURLs.add(ASN1OctetString.decodeAsOctetString(e).stringValue());
197          }
198    
199          return new SearchResultReferenceProtocolOp(referralURLs);
200        }
201        catch (final Exception e)
202        {
203          debugException(e);
204          throw new LDAPException(ResultCode.DECODING_ERROR,
205               ERR_SEARCH_REFERENCE_CANNOT_DECODE.get(getExceptionMessage(e)),
206               e);
207        }
208      }
209    
210    
211    
212      /**
213       * {@inheritDoc}
214       */
215      public void writeTo(final ASN1Buffer buffer)
216      {
217        final ASN1BufferSequence opSequence = buffer.beginSequence(
218             LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_RESULT_REFERENCE);
219        for (final String s : referralURLs)
220        {
221          buffer.addOctetString(s);
222        }
223        opSequence.end();
224      }
225    
226    
227    
228      /**
229       * Creates a search result reference from this protocol op.
230       *
231       * @param  controls  The set of controls to include in the search result
232       *                   reference.  It may be empty or {@code null} if no
233       *                   controls should be included.
234       *
235       * @return  The search result reference that was created.
236       */
237      public SearchResultReference toSearchResultReference(
238                                        final Control... controls)
239      {
240        final String[] referralArray = new String[referralURLs.size()];
241        referralURLs.toArray(referralArray);
242    
243        return new SearchResultReference(referralArray, controls);
244      }
245    
246    
247    
248      /**
249       * Retrieves a string representation of this protocol op.
250       *
251       * @return  A string representation of this protocol op.
252       */
253      @Override()
254      public String toString()
255      {
256        final StringBuilder buffer = new StringBuilder();
257        toString(buffer);
258        return buffer.toString();
259      }
260    
261    
262    
263      /**
264       * {@inheritDoc}
265       */
266      public void toString(final StringBuilder buffer)
267      {
268        buffer.append("SearchResultReferenceProtocolOp(referralURLs={");
269    
270        final Iterator<String> iterator = referralURLs.iterator();
271        while (iterator.hasNext())
272        {
273          buffer.append('\'');
274          buffer.append(iterator.next());
275          buffer.append('\'');
276          if (iterator.hasNext())
277          {
278            buffer.append(',');
279          }
280        }
281    
282        buffer.append("})");
283      }
284    }