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