001 /*
002 * Copyright 2007-2013 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2013 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 bind result. This constructor
144 * may be used in creating custom subclasses.
145 *
146 * @param bindResult The bind result to use to create this bind result.
147 */
148 protected BindResult(final BindResult bindResult)
149 {
150 super(bindResult);
151
152 serverSASLCredentials = bindResult.serverSASLCredentials;
153 }
154
155
156
157 /**
158 * Creates a new bind result object with the provided message ID and with the
159 * protocol op and controls read from the given ASN.1 stream reader.
160 *
161 * @param messageID The LDAP message ID for the LDAP message that is
162 * associated with this bind result.
163 * @param messageSequence The ASN.1 stream reader sequence used in the
164 * course of reading the LDAP message elements.
165 * @param reader The ASN.1 stream reader from which to read the
166 * protocol op and controls.
167 *
168 * @return The decoded bind result.
169 *
170 * @throws LDAPException If a problem occurs while reading or decoding data
171 * from the ASN.1 stream reader.
172 */
173 static BindResult readBindResultFrom(final int messageID,
174 final ASN1StreamReaderSequence messageSequence,
175 final ASN1StreamReader reader)
176 throws LDAPException
177 {
178 try
179 {
180 final ASN1StreamReaderSequence protocolOpSequence =
181 reader.beginSequence();
182 final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
183
184 String matchedDN = reader.readString();
185 if (matchedDN.length() == 0)
186 {
187 matchedDN = null;
188 }
189
190 String diagnosticMessage = reader.readString();
191 if (diagnosticMessage.length() == 0)
192 {
193 diagnosticMessage = null;
194 }
195
196 String[] referralURLs = null;
197 ASN1OctetString serverSASLCredentials = null;
198 while (protocolOpSequence.hasMoreElements())
199 {
200 final byte type = (byte) reader.peek();
201 switch (type)
202 {
203 case TYPE_REFERRAL_URLS:
204 final ArrayList<String> refList = new ArrayList<String>(1);
205 final ASN1StreamReaderSequence refSequence = reader.beginSequence();
206 while (refSequence.hasMoreElements())
207 {
208 refList.add(reader.readString());
209 }
210 referralURLs = new String[refList.size()];
211 refList.toArray(referralURLs);
212 break;
213
214 case TYPE_SERVER_SASL_CREDENTIALS:
215 serverSASLCredentials =
216 new ASN1OctetString(type, reader.readBytes());
217 break;
218
219 default:
220 throw new LDAPException(ResultCode.DECODING_ERROR,
221 ERR_BIND_RESULT_INVALID_ELEMENT.get(toHex(type)));
222 }
223 }
224
225 Control[] controls = NO_CONTROLS;
226 if (messageSequence.hasMoreElements())
227 {
228 final ArrayList<Control> controlList = new ArrayList<Control>(1);
229 final ASN1StreamReaderSequence controlSequence = reader.beginSequence();
230 while (controlSequence.hasMoreElements())
231 {
232 controlList.add(Control.readFrom(reader));
233 }
234
235 controls = new Control[controlList.size()];
236 controlList.toArray(controls);
237 }
238
239 return new BindResult(messageID, resultCode, diagnosticMessage, matchedDN,
240 referralURLs, controls, serverSASLCredentials);
241 }
242 catch (LDAPException le)
243 {
244 debugException(le);
245 throw le;
246 }
247 catch (Exception e)
248 {
249 debugException(e);
250 throw new LDAPException(ResultCode.DECODING_ERROR,
251 ERR_BIND_RESULT_CANNOT_DECODE.get(getExceptionMessage(e)), e);
252 }
253 }
254
255
256
257 /**
258 * Retrieves the server SASL credentials from the bind result, if available.
259 *
260 * @return The server SASL credentials from the bind response, or
261 * {@code null} if none were provided.
262 */
263 public ASN1OctetString getServerSASLCredentials()
264 {
265 return serverSASLCredentials;
266 }
267 }