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.io.Serializable;
026 import java.util.ArrayList;
027
028 import com.unboundid.asn1.ASN1StreamReader;
029 import com.unboundid.asn1.ASN1StreamReaderSequence;
030 import com.unboundid.ldap.protocol.LDAPResponse;
031
032 import static com.unboundid.ldap.sdk.LDAPMessages.*;
033 import static com.unboundid.util.Debug.*;
034 import static com.unboundid.util.StaticUtils.*;
035 import static com.unboundid.util.Validator.*;
036
037
038
039 /**
040 * This class provides a data structure for representing an LDAP search result
041 * reference. A search result reference consists of a set of referral URLs and
042 * may also include zero or more controls. It describes an alternate location
043 * in which additional results for the search may be found. If there are
044 * multiple referral URLs, then they should all be considered equivalent ways
045 * to access the information (e.g., referrals referencing different servers that
046 * may be contacted).
047 */
048 public final class SearchResultReference
049 implements Serializable, LDAPResponse
050 {
051 /**
052 * The serial version UID for this serializable class.
053 */
054 private static final long serialVersionUID = 5675961266319346053L;
055
056
057
058 // The set of controls returned with this search result reference.
059 private final Control[] controls;
060
061 // The message ID for the LDAP message containing this response.
062 private final int messageID;
063
064 // The set of referral URLs for this search result reference.
065 private final String[] referralURLs;
066
067
068
069 /**
070 * Creates a new search result reference with the provided information.
071 *
072 * @param referralURLs The set of referral URLs for this search result
073 * reference. It must not be {@code null}.
074 * @param controls The set of controls returned with this search result
075 * reference. It must not be {@code null}.
076 */
077 public SearchResultReference(final String[] referralURLs,
078 final Control[] controls)
079 {
080 this(-1, referralURLs, controls);
081 }
082
083
084
085 /**
086 * Creates a new search result reference with the provided information.
087 *
088 * @param messageID The message ID for the LDAP message containing this
089 * response.
090 * @param referralURLs The set of referral URLs for this search result
091 * reference. It must not be {@code null}.
092 * @param controls The set of controls returned with this search result
093 * reference. It must not be {@code null}.
094 */
095 public SearchResultReference(final int messageID, final String[] referralURLs,
096 final Control[] controls)
097 {
098 ensureNotNull(referralURLs);
099
100 this.messageID = messageID;
101 this.referralURLs = referralURLs;
102
103 if (controls == null)
104 {
105 this.controls = NO_CONTROLS;
106 }
107 else
108 {
109 this.controls = controls;
110 }
111 }
112
113
114
115 /**
116 * Creates a new search result reference object with the protocol op and
117 * controls read from the given ASN.1 stream reader.
118 *
119 * @param messageID The message ID for the LDAP message containing
120 * this response.
121 * @param messageSequence The ASN.1 stream reader sequence used in the
122 * course of reading the LDAP message elements.
123 * @param reader The ASN.1 stream reader from which to read the
124 * protocol op and controls.
125 *
126 * @return The decoded search result reference object.
127 *
128 * @throws LDAPException If a problem occurs while reading or decoding data
129 * from the ASN.1 stream reader.
130 */
131 static SearchResultReference readSearchReferenceFrom(final int messageID,
132 final ASN1StreamReaderSequence messageSequence,
133 final ASN1StreamReader reader)
134 throws LDAPException
135 {
136 try
137 {
138 final ArrayList<String> refList = new ArrayList<String>(5);
139 final ASN1StreamReaderSequence refSequence = reader.beginSequence();
140 while (refSequence.hasMoreElements())
141 {
142 refList.add(reader.readString());
143 }
144
145 final String[] referralURLs = new String[refList.size()];
146 refList.toArray(referralURLs);
147
148 Control[] controls = NO_CONTROLS;
149 if (messageSequence.hasMoreElements())
150 {
151 final ArrayList<Control> controlList = new ArrayList<Control>(5);
152 final ASN1StreamReaderSequence controlSequence = reader.beginSequence();
153 while (controlSequence.hasMoreElements())
154 {
155 controlList.add(Control.readFrom(reader));
156 }
157
158 controls = new Control[controlList.size()];
159 controlList.toArray(controls);
160 }
161
162 return new SearchResultReference(messageID, referralURLs, controls);
163 }
164 catch (LDAPException le)
165 {
166 debugException(le);
167 throw le;
168 }
169 catch (Exception e)
170 {
171 debugException(e);
172 throw new LDAPException(ResultCode.DECODING_ERROR,
173 ERR_SEARCH_REFERENCE_CANNOT_DECODE.get(getExceptionMessage(e)), e);
174 }
175 }
176
177
178
179 /**
180 * {@inheritDoc}
181 */
182 public int getMessageID()
183 {
184 return messageID;
185 }
186
187
188
189 /**
190 * Retrieves the set of referral URLs for this search result reference.
191 *
192 * @return The set of referral URLs for this search result reference.
193 */
194 public String[] getReferralURLs()
195 {
196 return referralURLs;
197 }
198
199
200
201 /**
202 * Retrieves the set of controls returned with this search result reference.
203 * Individual response controls of a specific type may be retrieved and
204 * decoded using the {@code get} method in the response control class.
205 *
206 * @return The set of controls returned with this search result reference.
207 */
208 public Control[] getControls()
209 {
210 return controls;
211 }
212
213
214
215 /**
216 * Retrieves the control with the specified OID. If there is more than one
217 * control with the given OID, then the first will be returned.
218 *
219 * @param oid The OID of the control to retrieve.
220 *
221 * @return The control with the requested OID, or {@code null} if there is no
222 * such control for this search result reference.
223 */
224 public Control getControl(final String oid)
225 {
226 for (final Control c : controls)
227 {
228 if (c.getOID().equals(oid))
229 {
230 return c;
231 }
232 }
233
234 return null;
235 }
236
237
238
239 /**
240 * Retrieves a string representation of this search result reference.
241 *
242 * @return A string representation of this search result reference.
243 */
244 @Override()
245 public String toString()
246 {
247 final StringBuilder buffer = new StringBuilder();
248 toString(buffer);
249 return buffer.toString();
250 }
251
252
253
254 /**
255 * Appends a string representation of this search result reference to the
256 * provided buffer.
257 *
258 * @param buffer The buffer to which to append the string representation of
259 * this search result reference.
260 */
261 public void toString(final StringBuilder buffer)
262 {
263 buffer.append("SearchResultReference(referralURLs={");
264 for (int i=0; i < referralURLs.length; i++)
265 {
266 if (i > 0)
267 {
268 buffer.append(", ");
269 }
270 buffer.append(referralURLs[i]);
271 }
272 buffer.append('}');
273
274 if (messageID >= 0)
275 {
276 buffer.append(", messageID=");
277 buffer.append(messageID);
278 }
279
280 buffer.append(", controls={");
281
282 for (int i=0; i < controls.length; i++)
283 {
284 if (i > 0)
285 {
286 buffer.append(", ");
287 }
288
289 controls[i].toString(buffer);
290 }
291
292 buffer.append("})");
293 }
294 }