001 /* 002 * Copyright 2010-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2015 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.unboundidds.extensions; 022 023 024 025 import com.unboundid.asn1.ASN1Element; 026 import com.unboundid.asn1.ASN1OctetString; 027 import com.unboundid.asn1.ASN1Sequence; 028 import com.unboundid.ldap.sdk.Control; 029 import com.unboundid.ldap.sdk.IntermediateResponse; 030 import com.unboundid.ldap.sdk.LDAPException; 031 import com.unboundid.ldap.sdk.ResultCode; 032 import com.unboundid.util.Debug; 033 import com.unboundid.util.NotMutable; 034 import com.unboundid.util.StaticUtils; 035 import com.unboundid.util.ThreadSafety; 036 import com.unboundid.util.ThreadSafetyLevel; 037 038 import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 039 040 041 042 /** 043 * <BLOCKQUOTE> 044 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID 045 * LDAP SDK for Java. It is not available for use in applications that 046 * include only the Standard Edition of the LDAP SDK, and is not supported for 047 * use in conjunction with non-UnboundID products. 048 * </BLOCKQUOTE> 049 * This class provides an implementation of an intermediate response which 050 * indicates that the Directory Server may have already purged information about 051 * one or more changes. The missing changelog entries intermediate response 052 * value may be present, and if it is then it will have the following encoding: 053 * <PRE> 054 * MissingEntriesIntermediateResponse ::= SEQUENCE { 055 * message [0] OCTET STRING OPTIONAL, 056 * ... } 057 * </PRE> 058 */ 059 @NotMutable() 060 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 061 public final class MissingChangelogEntriesIntermediateResponse 062 extends IntermediateResponse 063 { 064 /** 065 * The OID (1.3.6.1.4.1.30221.2.6.12) for the get stream directory values 066 * intermediate response. 067 */ 068 public static final String 069 MISSING_CHANGELOG_ENTRIES_INTERMEDIATE_RESPONSE_OID = 070 "1.3.6.1.4.1.30221.2.6.12"; 071 072 073 074 /** 075 * The BER type for the response message. 076 */ 077 private static final byte TYPE_MESSAGE = (byte) 0x80; 078 079 080 081 /** 082 * The serial version UID for this serializable class. 083 */ 084 private static final long serialVersionUID = -4961560327295588578L; 085 086 087 088 // A message which may provide additional information about the missing 089 // changes. 090 private final String message; 091 092 093 094 /** 095 * Creates a new missing changelog entries intermediate response with the 096 * provided information. 097 * 098 * @param message A message which may provide additional information about 099 * the missing changes. It may be {@code null} if no 100 * message is available. 101 * @param controls The set of controls to include in the intermediate 102 * response. It may be {@code null} or empty if no controls 103 * should be included. 104 */ 105 public MissingChangelogEntriesIntermediateResponse(final String message, 106 final Control... controls) 107 { 108 super(MISSING_CHANGELOG_ENTRIES_INTERMEDIATE_RESPONSE_OID, 109 encodeValue(message), controls); 110 111 this.message = message; 112 } 113 114 115 116 /** 117 * Creates a new missing changelog entries intermediate response from the 118 * provided generic intermediate response. 119 * 120 * @param r The generic intermediate response to be decoded. 121 * 122 * @throws LDAPException If the provided intermediate response cannot be 123 * decoded as a missing changelog entries response. 124 */ 125 public MissingChangelogEntriesIntermediateResponse( 126 final IntermediateResponse r) 127 throws LDAPException 128 { 129 super(r); 130 131 final ASN1OctetString value = r.getValue(); 132 if (value == null) 133 { 134 message = null; 135 return; 136 } 137 138 final ASN1Sequence valueSequence; 139 try 140 { 141 valueSequence = ASN1Sequence.decodeAsSequence(value.getValue()); 142 } 143 catch (final Exception e) 144 { 145 Debug.debugException(e); 146 throw new LDAPException(ResultCode.DECODING_ERROR, 147 ERR_MISSING_CHANGELOG_ENTRIES_IR_VALUE_NOT_SEQUENCE.get( 148 StaticUtils.getExceptionMessage(e)), e); 149 } 150 151 String msg = null; 152 for (final ASN1Element e : valueSequence.elements()) 153 { 154 final byte type = e.getType(); 155 switch (type) 156 { 157 case TYPE_MESSAGE: 158 msg = ASN1OctetString.decodeAsOctetString(e).stringValue(); 159 break; 160 default: 161 throw new LDAPException(ResultCode.DECODING_ERROR, 162 ERR_MISSING_CHANGELOG_ENTRIES_IR_UNEXPECTED_VALUE_TYPE.get( 163 StaticUtils.toHex(type))); 164 } 165 } 166 167 message = msg; 168 } 169 170 171 172 /** 173 * Encodes the provided information in a form suitable for use as the value of 174 * this intermediate response. 175 * 176 * @param message A message which may provide additional information about 177 * the missing changes. It may be {@code null} if no message 178 * is available. 179 * 180 * @return The encoded value, or {@code null} if no value should be included 181 * in the intermediate response. 182 */ 183 private static ASN1OctetString encodeValue(final String message) 184 { 185 if (message == null) 186 { 187 return null; 188 } 189 190 final ASN1Sequence valueSequence = new ASN1Sequence( 191 new ASN1OctetString(TYPE_MESSAGE, message)); 192 return new ASN1OctetString(valueSequence.encode()); 193 } 194 195 196 197 /** 198 * Retrieves a message which may provide additional information about the 199 * missing changes. 200 * 201 * @return A message which may provide additional information about the 202 * missing changes, or {@code null} if none is available. 203 */ 204 public String getMessage() 205 { 206 return message; 207 } 208 209 210 211 /** 212 * {@inheritDoc} 213 */ 214 @Override() 215 public String getIntermediateResponseName() 216 { 217 return INFO_MISSING_CHANGELOG_ENTRIES_IR_NAME.get(); 218 } 219 220 221 222 /** 223 * {@inheritDoc} 224 */ 225 @Override() 226 public String valueToString() 227 { 228 if (message == null) 229 { 230 return null; 231 } 232 233 final StringBuilder buffer = new StringBuilder(); 234 235 buffer.append("message='"); 236 buffer.append(message); 237 buffer.append('\''); 238 239 return buffer.toString(); 240 } 241 242 243 244 /** 245 * {@inheritDoc} 246 */ 247 @Override() 248 public void toString(final StringBuilder buffer) 249 { 250 buffer.append("MissingChangelogEntriesIntermediateResponse("); 251 252 boolean appended = false; 253 final int messageID = getMessageID(); 254 if (messageID >= 0) 255 { 256 buffer.append("messageID="); 257 buffer.append(messageID); 258 appended = true; 259 } 260 261 if (message != null) 262 { 263 if (appended) 264 { 265 buffer.append(", "); 266 } 267 268 buffer.append("message='"); 269 buffer.append(message); 270 buffer.append('\''); 271 appended = true; 272 } 273 274 final Control[] controls = getControls(); 275 if (controls.length > 0) 276 { 277 if (appended) 278 { 279 buffer.append(", "); 280 } 281 282 buffer.append("controls={"); 283 for (int i=0; i < controls.length; i++) 284 { 285 if (i > 0) 286 { 287 buffer.append(", "); 288 } 289 290 buffer.append(controls[i]); 291 } 292 buffer.append('}'); 293 } 294 295 buffer.append(')'); 296 } 297 }