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.ASN1StreamReader;
033 import com.unboundid.asn1.ASN1StreamReaderSequence;
034 import com.unboundid.ldap.sdk.Control;
035 import com.unboundid.ldap.sdk.LDAPException;
036 import com.unboundid.ldap.sdk.LDAPResult;
037 import com.unboundid.ldap.sdk.ResultCode;
038 import com.unboundid.util.InternalUseOnly;
039
040 import static com.unboundid.ldap.protocol.ProtocolMessages.*;
041 import static com.unboundid.util.Debug.*;
042 import static com.unboundid.util.StaticUtils.*;
043 import static com.unboundid.util.Validator.*;
044
045
046
047 /**
048 * This class provides an implementation of a generic response protocol op.
049 * It must be subclassed by classes providing implementations for each
050 * operation type.
051 */
052 @InternalUseOnly()
053 public abstract class GenericResponseProtocolOp
054 implements ProtocolOp
055 {
056 /**
057 * The BER type for the referral URLs elements.
058 */
059 public static final byte TYPE_REFERRALS = (byte) 0xA3;
060
061
062
063 /**
064 * The serial version UID for this serializable class.
065 */
066 private static final long serialVersionUID = 3837308973105414874L;
067
068
069
070 // The BER type for this response.
071 private final byte type;
072
073 // The result code for this response.
074 private final int resultCode;
075
076 // The referral URLs for this response.
077 private final List<String> referralURLs;
078
079 // The diagnostic message for this response.
080 private final String diagnosticMessage;
081
082 // The matched DN for this response.Static
083 private final String matchedDN;
084
085
086
087 /**
088 * Creates a new instance of this response with the provided information.
089 *
090 * @param type The BER type for this response.
091 * @param resultCode The result code for this response.
092 * @param matchedDN The matched DN for this result, if available.
093 * @param diagnosticMessage The diagnostic message for this response, if
094 * available.
095 * @param referralURLs The list of referral URLs for this response, if
096 * available.
097 */
098 protected GenericResponseProtocolOp(final byte type, final int resultCode,
099 final String matchedDN,
100 final String diagnosticMessage,
101 final List<String> referralURLs)
102 {
103 this.type = type;
104 this.resultCode = resultCode;
105 this.matchedDN = matchedDN;
106 this.diagnosticMessage = diagnosticMessage;
107
108 if (referralURLs == null)
109 {
110 this.referralURLs = Collections.emptyList();
111 }
112 else
113 {
114 this.referralURLs = Collections.unmodifiableList(referralURLs);
115 }
116 }
117
118
119
120 /**
121 * Creates a new response read from the provided ASN.1 stream reader.
122 *
123 * @param reader The ASN.1 stream reader from which to read the response.
124 *
125 * @throws LDAPException If a problem occurs while reading or parsing the
126 * response.
127 */
128 protected GenericResponseProtocolOp(final ASN1StreamReader reader)
129 throws LDAPException
130 {
131 try
132 {
133 type = (byte) reader.peek();
134 final ASN1StreamReaderSequence opSequence = reader.beginSequence();
135 resultCode = reader.readEnumerated();
136
137 String s = reader.readString();
138 ensureNotNull(s);
139 if (s.length() == 0)
140 {
141 matchedDN = null;
142 }
143 else
144 {
145 matchedDN = s;
146 }
147
148 s = reader.readString();
149 ensureNotNull(s);
150 if (s.length() == 0)
151 {
152 diagnosticMessage = null;
153 }
154 else
155 {
156 diagnosticMessage = s;
157 }
158
159 if (opSequence.hasMoreElements())
160 {
161 final ArrayList<String> refs = new ArrayList<String>(1);
162 final ASN1StreamReaderSequence refSequence = reader.beginSequence();
163 while (refSequence.hasMoreElements())
164 {
165 refs.add(reader.readString());
166 }
167 referralURLs = Collections.unmodifiableList(refs);
168 }
169 else
170 {
171 referralURLs = Collections.emptyList();
172 }
173 }
174 catch (Exception e)
175 {
176 debugException(e);
177 throw new LDAPException(ResultCode.DECODING_ERROR,
178 ERR_RESPONSE_CANNOT_DECODE.get(getExceptionMessage(e)), e);
179 }
180 }
181
182
183
184 /**
185 * Retrieves the result code for this response.
186 *
187 * @return The result code for this response.
188 */
189 public final int getResultCode()
190 {
191 return resultCode;
192 }
193
194
195
196 /**
197 * Retrieves the matched DN for this response, if any.
198 *
199 * @return The matched DN for this response, or {@code null} if there is
200 * no matched DN.
201 */
202 public final String getMatchedDN()
203 {
204 return matchedDN;
205 }
206
207
208
209 /**
210 * Retrieves the diagnostic message for this response, if any.
211 *
212 * @return The diagnostic message for this response, or {@code null} if there
213 * is no diagnostic message.
214 */
215 public final String getDiagnosticMessage()
216 {
217 return diagnosticMessage;
218 }
219
220
221
222 /**
223 * Retrieves the list of referral URLs for this response.
224 *
225 * @return The list of referral URLs for this response, or an empty list
226 * if there are no referral URLs.
227 */
228 public final List<String> getReferralURLs()
229 {
230 return referralURLs;
231 }
232
233
234
235 /**
236 * {@inheritDoc}
237 */
238 public byte getProtocolOpType()
239 {
240 return type;
241 }
242
243
244
245 /**
246 * {@inheritDoc}
247 */
248 public final void writeTo(final ASN1Buffer buffer)
249 {
250 final ASN1BufferSequence opSequence = buffer.beginSequence(type);
251 buffer.addEnumerated(resultCode);
252 buffer.addOctetString(matchedDN);
253 buffer.addOctetString(diagnosticMessage);
254
255 if (! referralURLs.isEmpty())
256 {
257 final ASN1BufferSequence refSequence =
258 buffer.beginSequence(TYPE_REFERRALS);
259 for (final String s : referralURLs)
260 {
261 buffer.addOctetString(s);
262 }
263 refSequence.end();
264 }
265 opSequence.end();
266 }
267
268
269
270 /**
271 * Creates a new LDAP result object from this response protocol op.
272 *
273 * @param controls The set of controls to include in the LDAP result. It
274 * may be empty or {@code null} if no controls should be
275 * included.
276 *
277 * @return The LDAP result that was created.
278 */
279 public LDAPResult toLDAPResult(final Control... controls)
280 {
281 final String[] refs;
282 if (referralURLs.isEmpty())
283 {
284 refs = NO_STRINGS;
285 }
286 else
287 {
288 refs = new String[referralURLs.size()];
289 referralURLs.toArray(refs);
290 }
291
292 return new LDAPResult(-1, ResultCode.valueOf(resultCode), diagnosticMessage,
293 matchedDN, refs, controls);
294 }
295
296
297
298 /**
299 * Retrieves a string representation of this protocol op.
300 *
301 * @return A string representation of this protocol op.
302 */
303 @Override()
304 public final String toString()
305 {
306 final StringBuilder buffer = new StringBuilder();
307 toString(buffer);
308 return buffer.toString();
309 }
310
311
312
313 /**
314 * {@inheritDoc}
315 */
316 public final void toString(final StringBuilder buffer)
317 {
318 buffer.append("ResponseProtocolOp(type=");
319 toHex(type, buffer);
320 buffer.append(", resultCode=");
321 buffer.append(resultCode);
322
323 if (matchedDN != null)
324 {
325 buffer.append(", matchedDN='");
326 buffer.append(matchedDN);
327 buffer.append('\'');
328 }
329
330 if (diagnosticMessage != null)
331 {
332 buffer.append(", diagnosticMessage='");
333 buffer.append(diagnosticMessage);
334 buffer.append('\'');
335 }
336
337 if (! referralURLs.isEmpty())
338 {
339 buffer.append(", referralURLs={");
340
341 final Iterator<String> iterator = referralURLs.iterator();
342 while (iterator.hasNext())
343 {
344 buffer.append('\'');
345 buffer.append(iterator.next());
346 buffer.append('\'');
347 if (iterator.hasNext())
348 {
349 buffer.append(',');
350 }
351 }
352
353 buffer.append('}');
354 }
355 buffer.append(')');
356 }
357 }