001 /*
002 * Copyright 2007-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-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.sdk;
022
023
024
025 import java.util.ArrayList;
026
027 import com.unboundid.asn1.ASN1OctetString;
028 import com.unboundid.asn1.ASN1StreamReader;
029 import com.unboundid.asn1.ASN1StreamReaderSequence;
030 import com.unboundid.util.Extensible;
031 import com.unboundid.util.NotMutable;
032 import com.unboundid.util.ThreadSafety;
033 import com.unboundid.util.ThreadSafetyLevel;
034
035 import static com.unboundid.ldap.sdk.LDAPMessages.*;
036 import static com.unboundid.util.Debug.*;
037 import static com.unboundid.util.StaticUtils.*;
038
039
040
041 /**
042 * This class provides a data structure for holding information about the result
043 * of processing a bind operation. It provides generic bind response elements
044 * as described in the {@link LDAPResult} class, but may be overridden to
045 * provide more detailed information for specific types of bind requests.
046 */
047 @Extensible()
048 @NotMutable()
049 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
050 public class BindResult
051 extends LDAPResult
052 {
053 /**
054 * The BER type for the server SASL credentials element in the bind result.
055 */
056 private static final byte TYPE_SERVER_SASL_CREDENTIALS = (byte) 0x87;
057
058
059
060 /**
061 * The serial version UID for this serializable class.
062 */
063 private static final long serialVersionUID = 2211625049303605730L;
064
065
066
067 // The server SASL credentials from the response, if available.
068 private final ASN1OctetString serverSASLCredentials;
069
070
071
072 /**
073 * Creates a new bind result with the provided information.
074 *
075 * @param messageID The message ID for the LDAP message that is
076 * associated with this bind result.
077 * @param resultCode The result code from the response.
078 * @param diagnosticMessage The diagnostic message from the response, if
079 * available.
080 * @param matchedDN The matched DN from the response, if available.
081 * @param referralURLs The set of referral URLs from the response, if
082 * available.
083 * @param responseControls The set of controls from the response, if
084 * available.
085 */
086 public BindResult(final int messageID, final ResultCode resultCode,
087 final String diagnosticMessage, final String matchedDN,
088 final String[] referralURLs,
089 final Control[] responseControls)
090 {
091 this(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
092 responseControls, null);
093 }
094
095
096
097 /**
098 * Creates a new bind result with the provided information.
099 *
100 * @param messageID The message ID for the LDAP message that is
101 * associated with this bind result.
102 * @param resultCode The result code from the response.
103 * @param diagnosticMessage The diagnostic message from the response, if
104 * available.
105 * @param matchedDN The matched DN from the response, if
106 * available.
107 * @param referralURLs The set of referral URLs from the response,
108 * if available.
109 * @param responseControls The set of controls from the response, if
110 * available.
111 * @param serverSASLCredentials The server SASL credentials from the
112 * response, if available.
113 */
114 public BindResult(final int messageID, final ResultCode resultCode,
115 final String diagnosticMessage, final String matchedDN,
116 final String[] referralURLs,
117 final Control[] responseControls,
118 final ASN1OctetString serverSASLCredentials)
119 {
120 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
121 responseControls);
122
123 this.serverSASLCredentials = serverSASLCredentials;
124 }
125
126
127
128 /**
129 * Creates a new bind result from the provided generic LDAP result.
130 *
131 * @param ldapResult The LDAP result to use to create this bind result.
132 */
133 public BindResult(final LDAPResult ldapResult)
134 {
135 super(ldapResult);
136
137 serverSASLCredentials = null;
138 }
139
140
141
142 /**
143 * Creates a new bind result from the provided {@code LDAPException}.
144 *
145 * @param exception The {@code LDAPException} to use to create this bind
146 * result.
147 */
148 public BindResult(final LDAPException exception)
149 {
150 super(exception.toLDAPResult());
151
152 serverSASLCredentials = null;
153 }
154
155
156
157 /**
158 * Creates a new bind result from the provided bind result. This constructor
159 * may be used in creating custom subclasses.
160 *
161 * @param bindResult The bind result to use to create this bind result.
162 */
163 protected BindResult(final BindResult bindResult)
164 {
165 super(bindResult);
166
167 serverSASLCredentials = bindResult.serverSASLCredentials;
168 }
169
170
171
172 /**
173 * Creates a new bind result object with the provided message ID and with the
174 * protocol op and controls read from the given ASN.1 stream reader.
175 *
176 * @param messageID The LDAP message ID for the LDAP message that is
177 * associated with this bind result.
178 * @param messageSequence The ASN.1 stream reader sequence used in the
179 * course of reading the LDAP message elements.
180 * @param reader The ASN.1 stream reader from which to read the
181 * protocol op and controls.
182 *
183 * @return The decoded bind result.
184 *
185 * @throws LDAPException If a problem occurs while reading or decoding data
186 * from the ASN.1 stream reader.
187 */
188 static BindResult readBindResultFrom(final int messageID,
189 final ASN1StreamReaderSequence messageSequence,
190 final ASN1StreamReader reader)
191 throws LDAPException
192 {
193 try
194 {
195 final ASN1StreamReaderSequence protocolOpSequence =
196 reader.beginSequence();
197 final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
198
199 String matchedDN = reader.readString();
200 if (matchedDN.length() == 0)
201 {
202 matchedDN = null;
203 }
204
205 String diagnosticMessage = reader.readString();
206 if (diagnosticMessage.length() == 0)
207 {
208 diagnosticMessage = null;
209 }
210
211 String[] referralURLs = null;
212 ASN1OctetString serverSASLCredentials = null;
213 while (protocolOpSequence.hasMoreElements())
214 {
215 final byte type = (byte) reader.peek();
216 switch (type)
217 {
218 case TYPE_REFERRAL_URLS:
219 final ArrayList<String> refList = new ArrayList<String>(1);
220 final ASN1StreamReaderSequence refSequence = reader.beginSequence();
221 while (refSequence.hasMoreElements())
222 {
223 refList.add(reader.readString());
224 }
225 referralURLs = new String[refList.size()];
226 refList.toArray(referralURLs);
227 break;
228
229 case TYPE_SERVER_SASL_CREDENTIALS:
230 serverSASLCredentials =
231 new ASN1OctetString(type, reader.readBytes());
232 break;
233
234 default:
235 throw new LDAPException(ResultCode.DECODING_ERROR,
236 ERR_BIND_RESULT_INVALID_ELEMENT.get(toHex(type)));
237 }
238 }
239
240 Control[] controls = NO_CONTROLS;
241 if (messageSequence.hasMoreElements())
242 {
243 final ArrayList<Control> controlList = new ArrayList<Control>(1);
244 final ASN1StreamReaderSequence controlSequence = reader.beginSequence();
245 while (controlSequence.hasMoreElements())
246 {
247 controlList.add(Control.readFrom(reader));
248 }
249
250 controls = new Control[controlList.size()];
251 controlList.toArray(controls);
252 }
253
254 return new BindResult(messageID, resultCode, diagnosticMessage, matchedDN,
255 referralURLs, controls, serverSASLCredentials);
256 }
257 catch (LDAPException le)
258 {
259 debugException(le);
260 throw le;
261 }
262 catch (Exception e)
263 {
264 debugException(e);
265 throw new LDAPException(ResultCode.DECODING_ERROR,
266 ERR_BIND_RESULT_CANNOT_DECODE.get(getExceptionMessage(e)), e);
267 }
268 }
269
270
271
272 /**
273 * Retrieves the server SASL credentials from the bind result, if available.
274 *
275 * @return The server SASL credentials from the bind response, or
276 * {@code null} if none were provided.
277 */
278 public ASN1OctetString getServerSASLCredentials()
279 {
280 return serverSASLCredentials;
281 }
282 }