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    }