001 /* 002 * Copyright 2007-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2008-2015 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 }