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