001 /* 002 * Copyright 2009-2016 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2009-2016 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 }