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.Attribute; 038 import com.unboundid.ldap.sdk.Control; 039 import com.unboundid.ldap.sdk.Entry; 040 import com.unboundid.ldap.sdk.LDAPException; 041 import com.unboundid.ldap.sdk.ResultCode; 042 import com.unboundid.ldap.sdk.SearchResultEntry; 043 import com.unboundid.util.InternalUseOnly; 044 045 import static com.unboundid.ldap.protocol.ProtocolMessages.*; 046 import static com.unboundid.util.Debug.*; 047 import static com.unboundid.util.StaticUtils.*; 048 import static com.unboundid.util.Validator.*; 049 050 051 052 /** 053 * This class provides an implementation of an LDAP search result entry protocol 054 * op. 055 */ 056 @InternalUseOnly() 057 public final class SearchResultEntryProtocolOp 058 implements ProtocolOp 059 { 060 /** 061 * The serial version UID for this serializable class. 062 */ 063 private static final long serialVersionUID = 6501366526364541767L; 064 065 066 067 // The list of attributes for this search result entry. 068 private final List<Attribute> attributes; 069 070 // The entry DN for this search result entry. 071 private final String dn; 072 073 074 075 /** 076 * Creates a new search result entry protocol op with the provided 077 * information. 078 * 079 * @param dn The entry DN for this search result entry. 080 * @param attributes The list of attributes to include in this search result 081 * entry. 082 */ 083 public SearchResultEntryProtocolOp(final String dn, 084 final List<Attribute> attributes) 085 { 086 this.dn = dn; 087 this.attributes = Collections.unmodifiableList(attributes); 088 } 089 090 091 092 /** 093 * Creates a new search result entry protocol op from the provided entry. 094 * 095 * @param entry The entry to use to create this protocol op. 096 */ 097 public SearchResultEntryProtocolOp(final Entry entry) 098 { 099 dn = entry.getDN(); 100 attributes = Collections.unmodifiableList(new ArrayList<Attribute>( 101 entry.getAttributes())); 102 } 103 104 105 106 /** 107 * Creates a new search result entry protocol op read from the provided ASN.1 108 * stream reader. 109 * 110 * @param reader The ASN.1 stream reader from which to read the search 111 * result entry protocol op. 112 * 113 * @throws LDAPException If a problem occurs while reading or parsing the 114 * search result entry. 115 */ 116 SearchResultEntryProtocolOp(final ASN1StreamReader reader) 117 throws LDAPException 118 { 119 try 120 { 121 reader.beginSequence(); 122 dn = reader.readString(); 123 ensureNotNull(dn); 124 125 final ArrayList<Attribute> attrs = new ArrayList<Attribute>(10); 126 final ASN1StreamReaderSequence attrSequence = reader.beginSequence(); 127 while (attrSequence.hasMoreElements()) 128 { 129 attrs.add(Attribute.readFrom(reader)); 130 } 131 132 attributes = Collections.unmodifiableList(attrs); 133 } 134 catch (LDAPException le) 135 { 136 debugException(le); 137 throw le; 138 } 139 catch (Exception e) 140 { 141 debugException(e); 142 143 throw new LDAPException(ResultCode.DECODING_ERROR, 144 ERR_SEARCH_ENTRY_CANNOT_DECODE.get(getExceptionMessage(e)), e); 145 } 146 } 147 148 149 150 /** 151 * Retrieves the DN for this search result entry. 152 * 153 * @return The DN for this search result entry. 154 */ 155 public String getDN() 156 { 157 return dn; 158 } 159 160 161 162 /** 163 * Retrieves the list of attributes for this search result entry. 164 * 165 * @return The list of attributes for this search result entry. 166 */ 167 public List<Attribute> getAttributes() 168 { 169 return attributes; 170 } 171 172 173 174 /** 175 * {@inheritDoc} 176 */ 177 public byte getProtocolOpType() 178 { 179 return LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_RESULT_ENTRY; 180 } 181 182 183 184 /** 185 * {@inheritDoc} 186 */ 187 public ASN1Element encodeProtocolOp() 188 { 189 final ArrayList<ASN1Element> attrElements = 190 new ArrayList<ASN1Element>(attributes.size()); 191 for (final Attribute a : attributes) 192 { 193 attrElements.add(a.encode()); 194 } 195 196 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_RESULT_ENTRY, 197 new ASN1OctetString(dn), 198 new ASN1Sequence(attrElements)); 199 } 200 201 202 203 /** 204 * Decodes the provided ASN.1 element as a search result entry protocol op. 205 * 206 * @param element The ASN.1 element to be decoded. 207 * 208 * @return The decoded search result entry protocol op. 209 * 210 * @throws LDAPException If the provided ASN.1 element cannot be decoded as 211 * a search result entry protocol op. 212 */ 213 public static SearchResultEntryProtocolOp decodeProtocolOp( 214 final ASN1Element element) 215 throws LDAPException 216 { 217 try 218 { 219 final ASN1Element[] elements = 220 ASN1Sequence.decodeAsSequence(element).elements(); 221 final String dn = 222 ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 223 224 final ASN1Element[] attrElements = 225 ASN1Sequence.decodeAsSequence(elements[1]).elements(); 226 final ArrayList<Attribute> attributes = 227 new ArrayList<Attribute>(attrElements.length); 228 for (final ASN1Element e : attrElements) 229 { 230 attributes.add(Attribute.decode(ASN1Sequence.decodeAsSequence(e))); 231 } 232 233 return new SearchResultEntryProtocolOp(dn, attributes); 234 } 235 catch (final Exception e) 236 { 237 debugException(e); 238 throw new LDAPException(ResultCode.DECODING_ERROR, 239 ERR_SEARCH_ENTRY_CANNOT_DECODE.get(getExceptionMessage(e)), 240 e); 241 } 242 } 243 244 245 246 /** 247 * {@inheritDoc} 248 */ 249 public void writeTo(final ASN1Buffer buffer) 250 { 251 final ASN1BufferSequence opSequence = 252 buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_RESULT_ENTRY); 253 buffer.addOctetString(dn); 254 255 final ASN1BufferSequence attrSequence = buffer.beginSequence(); 256 for (final Attribute a : attributes) 257 { 258 a.writeTo(buffer); 259 } 260 attrSequence.end(); 261 opSequence.end(); 262 } 263 264 265 266 /** 267 * Creates a search result entry from this protocol op. 268 * 269 * @param controls The set of controls to include in the search result 270 * entry. It may be empty or {@code null} if no controls 271 * should be included. 272 * 273 * @return The search result entry that was created. 274 */ 275 public SearchResultEntry toSearchResultEntry(final Control... controls) 276 { 277 return new SearchResultEntry(dn, attributes, controls); 278 } 279 280 281 282 /** 283 * Retrieves a string representation of this protocol op. 284 * 285 * @return A string representation of this protocol op. 286 */ 287 @Override() 288 public String toString() 289 { 290 final StringBuilder buffer = new StringBuilder(); 291 toString(buffer); 292 return buffer.toString(); 293 } 294 295 296 297 /** 298 * {@inheritDoc} 299 */ 300 public void toString(final StringBuilder buffer) 301 { 302 buffer.append("SearchResultEntryProtocolOp(dn='"); 303 buffer.append(dn); 304 buffer.append("', attrs={"); 305 306 final Iterator<Attribute> iterator = attributes.iterator(); 307 while (iterator.hasNext()) 308 { 309 iterator.next().toString(buffer); 310 if (iterator.hasNext()) 311 { 312 buffer.append(','); 313 } 314 } 315 316 buffer.append("})"); 317 } 318 }