001/*
002 * Copyright 2018-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2018-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) 2018-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.logs;
037
038
039
040import java.util.Collections;
041import java.util.List;
042
043import com.unboundid.ldap.sdk.ChangeType;
044import com.unboundid.ldap.sdk.ReadOnlyEntry;
045import com.unboundid.ldap.sdk.unboundidds.controls.SoftDeleteRequestControl;
046import com.unboundid.ldif.LDIFAddChangeRecord;
047import com.unboundid.ldif.LDIFChangeRecord;
048import com.unboundid.ldif.LDIFDeleteChangeRecord;
049import com.unboundid.ldif.LDIFException;
050import com.unboundid.ldif.LDIFReader;
051import com.unboundid.util.Debug;
052import com.unboundid.util.StaticUtils;
053import com.unboundid.util.ThreadSafety;
054import com.unboundid.util.ThreadSafetyLevel;
055
056import static com.unboundid.ldap.sdk.unboundidds.logs.LogMessages.*;
057
058
059
060/**
061 * This class provides a data structure that holds information about an audit
062 * log message that represents an add operation.
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@ThreadSafety(level= ThreadSafetyLevel.COMPLETELY_THREADSAFE)
075public final class AddAuditLogMessage
076       extends AuditLogMessage
077{
078  /**
079   * Retrieves the serial version UID for this serializable class.
080   */
081  private static final long serialVersionUID = -4103749134439291911L;
082
083
084
085  // Indicates whether the add operation represents an undelete of a
086  // soft-deleted entry.
087  private final Boolean isUndelete;
088
089  // An LDIF change record that encapsulates the change represented by this add
090  // audit log message.
091  private final LDIFAddChangeRecord addChangeRecord;
092
093  // The entry included in the undelete request.
094  private final ReadOnlyEntry undeleteRequestEntry;
095
096
097
098  /**
099   * Creates a new add audit log message from the provided set of lines.
100   *
101   * @param  logMessageLines  The lines that comprise the log message.  It must
102   *                          not be {@code null} or empty, and it must not
103   *                          contain any blank lines, although it may contain
104   *                          comments.  In fact, it must contain at least one
105   *                          comment line that appears before any non-comment
106   *                          lines (but possibly after other comment lines)
107   *                          that serves as the message header.
108   *
109   * @throws  AuditLogException  If a problem is encountered while processing
110   *                             the provided list of log message lines.
111   */
112  public AddAuditLogMessage(final String... logMessageLines)
113         throws AuditLogException
114  {
115    this(StaticUtils.toList(logMessageLines), logMessageLines);
116  }
117
118
119
120  /**
121   * Creates a new add audit log message from the provided set of lines.
122   *
123   * @param  logMessageLines  The lines that comprise the log message.  It must
124   *                          not be {@code null} or empty, and it must not
125   *                          contain any blank lines, although it may contain
126   *                          comments.  In fact, it must contain at least one
127   *                          comment line that appears before any non-comment
128   *                          lines (but possibly after other comment lines)
129   *                          that serves as the message header.
130   *
131   * @throws  AuditLogException  If a problem is encountered while processing
132   *                             the provided list of log message lines.
133   */
134  public AddAuditLogMessage(final List<String> logMessageLines)
135         throws AuditLogException
136  {
137    this(logMessageLines, StaticUtils.toArray(logMessageLines, String.class));
138  }
139
140
141
142  /**
143   * Creates a new add audit log message from the provided information.
144   *
145   * @param  logMessageLineList   The lines that comprise the log message as a
146   *                              list.
147   * @param  logMessageLineArray  The lines that comprise the log message as an
148   *                              array.
149   *
150   * @throws  AuditLogException  If a problem is encountered while processing
151   *                             the provided list of log message lines.
152   */
153  private AddAuditLogMessage(final List<String> logMessageLineList,
154                             final String[] logMessageLineArray)
155          throws AuditLogException
156  {
157    super(logMessageLineList);
158
159    try
160    {
161      final LDIFChangeRecord changeRecord =
162           LDIFReader.decodeChangeRecord(logMessageLineArray);
163      if (!(changeRecord instanceof LDIFAddChangeRecord))
164      {
165        throw new AuditLogException(logMessageLineList,
166             ERR_ADD_AUDIT_LOG_MESSAGE_CHANGE_TYPE_NOT_ADD.get(
167                  changeRecord.getChangeType().getName(),
168                  ChangeType.ADD.getName()));
169      }
170
171      addChangeRecord = (LDIFAddChangeRecord) changeRecord;
172    }
173    catch (final LDIFException e)
174    {
175      Debug.debugException(e);
176      throw new AuditLogException(logMessageLineList,
177           ERR_ADD_AUDIT_LOG_MESSAGE_LINES_NOT_CHANGE_RECORD.get(
178                StaticUtils.getExceptionMessage(e)),
179           e);
180    }
181
182    isUndelete = getNamedValueAsBoolean("isUndelete", getHeaderNamedValues());
183    undeleteRequestEntry = decodeCommentedEntry("Undelete request entry",
184         logMessageLineList, null);
185  }
186
187
188
189  /**
190   * Creates a new add audit log message from the provided set of lines.
191   *
192   * @param  logMessageLines  The lines that comprise the log message.  It must
193   *                          not be {@code null} or empty, and it must not
194   *                          contain any blank lines, although it may contain
195   *                          comments.  In fact, it must contain at least one
196   *                          comment line that appears before any non-comment
197   *                          lines (but possibly after other comment lines)
198   *                          that serves as the message header.
199   * @param  addChangeRecord  The LDIF add change record that is described by
200   *                          the provided log message lines.
201   *
202   * @throws  AuditLogException  If a problem is encountered while processing
203   *                             the provided list of log message lines.
204   */
205  AddAuditLogMessage(final List<String> logMessageLines,
206                     final LDIFAddChangeRecord addChangeRecord)
207       throws AuditLogException
208  {
209    super(logMessageLines);
210
211    this.addChangeRecord = addChangeRecord;
212
213    isUndelete = getNamedValueAsBoolean("isUndelete", getHeaderNamedValues());
214    undeleteRequestEntry = decodeCommentedEntry("Undelete request entry",
215         logMessageLines, null);
216  }
217
218
219
220  /**
221   * {@inheritDoc}
222   */
223  @Override()
224  public String getDN()
225  {
226    return addChangeRecord.getDN();
227  }
228
229
230
231  /**
232   * Retrieves a read-only representation of the entry that was added.
233   *
234   * @return  A read-only representation of the entry that was added.
235   */
236  public ReadOnlyEntry getEntry()
237  {
238    return new ReadOnlyEntry(addChangeRecord.getEntryToAdd());
239  }
240
241
242
243  /**
244   * Retrieves the value of the "isUndelete" flag from this log message, which
245   * indicates whether the add operation attempted to undelete a previously
246   * soft-deleted entry, if available.
247   *
248   * @return  The value of the "isUndelete" flag from this log message, or
249   *          {@code null} if it is not available.
250   */
251  public Boolean getIsUndelete()
252  {
253    return isUndelete;
254  }
255
256
257
258  /**
259   * Retrieves the entry that comprised the undelete request, available.
260   *
261   * @return  The entry that comprised the undelete request, or {@code null} if
262   *          it is not available.
263   */
264  public ReadOnlyEntry getUndeleteRequestEntry()
265  {
266    return undeleteRequestEntry;
267  }
268
269
270
271  /**
272   * {@inheritDoc}
273   */
274  @Override()
275  public ChangeType getChangeType()
276  {
277    return ChangeType.ADD;
278  }
279
280
281
282  /**
283   * {@inheritDoc}
284   */
285  @Override()
286  public LDIFAddChangeRecord getChangeRecord()
287  {
288    return addChangeRecord;
289  }
290
291
292
293  /**
294   * {@inheritDoc}
295   */
296  @Override()
297  public boolean isRevertible()
298  {
299    // Add audit log messages are always reversible.
300    return true;
301  }
302
303
304
305  /**
306   * {@inheritDoc}
307   */
308  @Override()
309  public List<LDIFChangeRecord> getRevertChangeRecords()
310  {
311    if ((isUndelete != null) && isUndelete)
312    {
313      return Collections.<LDIFChangeRecord>singletonList(
314           new LDIFDeleteChangeRecord(
315                SoftDeleteRequestControl.createSoftDeleteRequest(
316                     addChangeRecord.getDN(), false, true)));
317    }
318    else
319    {
320      return Collections.<LDIFChangeRecord>singletonList(
321           new LDIFDeleteChangeRecord(addChangeRecord.getDN()));
322    }
323  }
324
325
326
327  /**
328   * {@inheritDoc}
329   */
330  @Override()
331  public void toString(final StringBuilder buffer)
332  {
333    buffer.append(getUncommentedHeaderLine());
334    buffer.append("; changeType=add; dn=\"");
335    buffer.append(addChangeRecord.getDN());
336    buffer.append('\"');
337  }
338}