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 */ 021package com.unboundid.ldap.sdk; 022 023 024 025import java.util.ArrayList; 026 027import com.unboundid.asn1.ASN1OctetString; 028import com.unboundid.asn1.ASN1StreamReader; 029import com.unboundid.asn1.ASN1StreamReaderSequence; 030import com.unboundid.util.Extensible; 031import com.unboundid.util.NotMutable; 032import com.unboundid.util.ThreadSafety; 033import com.unboundid.util.ThreadSafetyLevel; 034 035import static com.unboundid.ldap.sdk.LDAPMessages.*; 036import static com.unboundid.util.Debug.*; 037import 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) 050public 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}