001/*
002 * Copyright 2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2020 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2020 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.extensions;
037
038
039
040import java.util.Date;
041
042import com.unboundid.asn1.ASN1Element;
043import com.unboundid.asn1.ASN1OctetString;
044import com.unboundid.asn1.ASN1Sequence;
045import com.unboundid.ldap.sdk.LDAPException;
046import com.unboundid.ldap.sdk.ResultCode;
047import com.unboundid.util.Debug;
048import com.unboundid.util.NotMutable;
049import com.unboundid.util.StaticUtils;
050import com.unboundid.util.ThreadSafety;
051import com.unboundid.util.ThreadSafetyLevel;
052import com.unboundid.util.Validator;
053
054import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
055
056
057
058/**
059 * This class provides a collect support data log capture window implementation
060 * that indicates that the tool should capture information for a specified
061 * window of time (between start and end times, inclusive) when processing a
062 * {@link CollectSupportDataExtendedRequest}.
063 * <BR>
064 * <BLOCKQUOTE>
065 *   <B>NOTE:</B>  This class, and other classes within the
066 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
067 *   supported for use against Ping Identity, UnboundID, and
068 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
069 *   for proprietary functionality or for external specifications that are not
070 *   considered stable or mature enough to be guaranteed to work in an
071 *   interoperable way with other types of LDAP servers.
072 * </BLOCKQUOTE>
073 *
074 * @see  CollectSupportDataExtendedRequest
075 */
076@NotMutable()
077@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
078public final class TimeWindowCollectSupportDataLogCaptureWindow
079       extends CollectSupportDataLogCaptureWindow
080{
081  /**
082   * The serial version UID for this serializable class.
083   */
084  private static final long serialVersionUID = -989944420134047411L;
085
086
087
088  // An ASN.1 element that provides an encoded representation of this time
089  // window collect support data log capture window.
090  private final ASN1Element encodedWindow;
091
092  // The end time for the window.
093  private final Long endTimeMillis;
094
095  // The start time for the window.
096  private final long startTimeMillis;
097
098
099
100  /**
101   * Creates a new instance of this collect support data log capture window
102   * object that will capture log content within the specified window of time.
103   *
104   * @param  startTime  The time of the oldest log messages to include in the
105   *                    support data archive.  It must be non-{@code null}, and
106   *                    it must represent a time no earlier than midnight on
107   *                    January 1, 1970, UTC.
108   * @param  endTime    The time of the most recent log messages to include in
109   *                    the support data archive.  This may be {@code null} if
110   *                    the end time should be set to the time the
111   *                    {@link CollectSupportDataExtendedRequest} was
112   *                    received by the server.  If it is non-{@code null}, then
113   *                    it must represent a time no earlier than the provided
114   *                    start time.
115   */
116  public TimeWindowCollectSupportDataLogCaptureWindow(final Date startTime,
117                                                      final Date endTime)
118  {
119    this(startTime.getTime(), (endTime == null ? null : endTime.getTime()));
120  }
121
122
123
124  /**
125   * Creates a new instance of this collect support data log capture window
126   * object that will capture log content within the specified window of time.
127   *
128   * @param  startTimeMillis  The time of the oldest log messages to include in
129   *                          the support data archive, represented as the
130   *                          number of milliseconds since midnight on January
131   *                          1, 1970, UTC (i.e., the format used by
132   *                          {@code System.currentTimeMillis()} and
133   *                          {@code Date.getTime()}).
134   * @param  endTimeMillis    The time of the most recent log messages to
135   *                          include in the support data archive, represented
136   *                          as the number of milliseconds since midnight on
137   *                          January 1, 1970, UTC.  This may be {@code null} if
138   *                          the end time should be set to the time the
139   *                          {@link CollectSupportDataExtendedRequest} was
140   *                          received by the server.  If it is
141   *                          non-{@code null}, then it must be greater than or
142   *                          equal to the provided start time.
143   */
144  public TimeWindowCollectSupportDataLogCaptureWindow(
145              final long startTimeMillis, final Long endTimeMillis)
146  {
147    Validator.ensureTrue((startTimeMillis > 0),
148         "TimeWindowCollectSupportDataLogCaptureWindow.startTimeMillis must " +
149              "be greater than zero.");
150    if (endTimeMillis != null)
151    {
152      Validator.ensureTrue((endTimeMillis >= startTimeMillis),
153           "If it is provided, then" +
154                "TimeWindowCollectSupportDataLogCaptureWindow.endTime must " +
155                "greater than or equal to " +
156                "TimeWindowCollectSupportDataLogCaptureWindow.endTime.");
157    }
158
159    this.startTimeMillis = startTimeMillis;
160    this.endTimeMillis = endTimeMillis;
161
162    if (endTimeMillis == null)
163    {
164      encodedWindow = new ASN1Sequence(TYPE_TIME_WINDOW,
165           new ASN1OctetString(StaticUtils.encodeGeneralizedTime(
166                startTimeMillis)));
167    }
168    else
169    {
170      encodedWindow = new ASN1Sequence(TYPE_TIME_WINDOW,
171           new ASN1OctetString(StaticUtils.encodeGeneralizedTime(
172                startTimeMillis)),
173           new ASN1OctetString(StaticUtils.encodeGeneralizedTime(
174                endTimeMillis)));
175    }
176  }
177
178
179
180  /**
181   * Retrieves the time of the oldest log messages to include in the support
182   * data archive.
183   *
184   * @return  The time of the oldest log messages to include in the support data
185   *          archive.
186   */
187  public Date getStartTime()
188  {
189    return new Date(startTimeMillis);
190  }
191
192
193
194  /**
195   * Retrieves the time of the oldest log messages to include in the support
196   * data archive, represented as the number of milliseconds since midnight on
197   * January 1, 1970, UTC (i.e., the format used by
198   * {@code System.currentTimeMillis()} and {@code Date.getTime()}).
199   *
200   * @return  The time of the oldest log messages to include in the support data
201   *          archive, represented as the number of milliseconds since midnight
202   *          on January 1, 1970, UTC.
203   */
204  public long getStartTimeMillis()
205  {
206    return startTimeMillis;
207  }
208
209
210
211  /**
212   * Retrieves the time of the most recent log messages to include in the
213   * support data archive, if specified.
214   *
215   * @return  The time of the most recent log messages to include in the
216   *          support data archive, or {@code null} if the end time should be
217   *          set to the time the {@link CollectSupportDataExtendedRequest} was
218   *          received by the server.
219   */
220  public Date getEndTime()
221  {
222    if (endTimeMillis == null)
223    {
224      return null;
225    }
226    else
227    {
228      return new Date(endTimeMillis);
229    }
230  }
231
232
233
234  /**
235   * Retrieves the time of the most recent log messages to include in the
236   * support data archive, if specified.  The value will represent the number of
237   * milliseconds since midnight on January 1, 1970, UTC (i.e., the format used
238   * by {@code System.currentTimeMillis()} and {@code Date.getTime()}).
239   *
240   * @return  The time of the most recent log messages to include in the
241   *          support data archive, or {@code null} if the end time should be
242   *          set to the time the {@link CollectSupportDataExtendedRequest} was
243   *          received by the server.
244   */
245  public Long getEndTimeMillis()
246  {
247    return endTimeMillis;
248  }
249
250
251
252  /**
253   * Decodes the provided ASN.1 element as a tool-default collect support data
254   * log capture window object.
255   *
256   * @param  e  The ASN.1 element to be decoded.  It must not be {@code null}.
257   *
258   * @return  The tool-default collect support data log capture window object
259   *          that was decoded.
260   *
261   * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
262   *                         a valid tool-default collect support data log
263   *                         capture window object.
264   */
265  static TimeWindowCollectSupportDataLogCaptureWindow
266              decodeInternal(final ASN1Element e)
267         throws LDAPException
268  {
269    try
270    {
271      final ASN1Element[] elements =
272           ASN1Sequence.decodeAsSequence(e).elements();
273      if (elements.length == 1)
274      {
275        final long startTimeMillis = decodeGeneralizedTimeString(elements[0]);
276        return new TimeWindowCollectSupportDataLogCaptureWindow(startTimeMillis,
277             null);
278      }
279      else if (elements.length == 2)
280      {
281        final long startTimeMillis = decodeGeneralizedTimeString(elements[0]);
282        final long endTimeMillis = decodeGeneralizedTimeString(elements[1]);
283        return new TimeWindowCollectSupportDataLogCaptureWindow(startTimeMillis,
284             endTimeMillis);
285      }
286      else
287      {
288        throw new LDAPException(ResultCode.DECODING_ERROR,
289             ERR_TIME_WINDOW_CSD_LOG_WINDOW_INVALID_ELEMENT_COUNT.get(
290                  elements.length));
291      }
292    }
293    catch (final LDAPException le)
294    {
295      Debug.debugException(le);
296      throw le;
297    }
298    catch (final Exception ex)
299    {
300      Debug.debugException(ex);
301      throw new LDAPException(ResultCode.DECODING_ERROR,
302           ERR_TIME_WINDOW_CSD_LOG_WINDOW_CANNOT_DECODE.get(
303                StaticUtils.getExceptionMessage(ex)),
304           ex);
305    }
306  }
307
308
309
310  /**
311   * Decodes the provided ASN.1 element as an octet string whose value is the
312   * generalized time representation of a timestamp.
313   *
314   * @param  e  The element from which the timestamp should be extracted.
315   *
316   * @return  The time (in milliseconds since the epoch) represented by the
317   *          timestamp.
318   *
319   * @throws  LDAPException  If the element value cannot be parsed as a valid
320   *                         timestamp in the generalized time format.
321   */
322  private static long decodeGeneralizedTimeString(final ASN1Element e)
323          throws LDAPException
324  {
325    final String timestampString =
326         ASN1OctetString.decodeAsOctetString(e).stringValue();
327
328    try
329    {
330      return StaticUtils.decodeGeneralizedTime(timestampString).getTime();
331    }
332    catch (final Exception ex)
333    {
334      Debug.debugException(ex);
335      throw new LDAPException(ResultCode.DECODING_ERROR,
336           ERR_TIME_WINDOW_CSD_LOG_WINDOW_MALFORMED_GT.get(timestampString),
337           ex);
338    }
339  }
340
341
342
343  /**
344   * {@inheritDoc}
345   */
346  @Override()
347  public ASN1Element encode()
348  {
349    return encodedWindow;
350  }
351
352
353
354  /**
355   * {@inheritDoc}
356   */
357  @Override()
358  public void toString(final StringBuilder buffer)
359  {
360    buffer.append("TimeWindowCollectSupportDataLogCaptureWindow(startTime='");
361    buffer.append(StaticUtils.encodeGeneralizedTime(startTimeMillis));
362    buffer.append('\'');
363
364    if (endTimeMillis != null)
365    {
366      buffer.append(", endTime='");
367      buffer.append(StaticUtils.encodeGeneralizedTime(endTimeMillis));
368      buffer.append('\'');
369    }
370
371    buffer.append(')');
372  }
373}