001/*
002 * Copyright 2009-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2009-2024 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) 2009-2024 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.io.BufferedReader;
041import java.io.Closeable;
042import java.io.File;
043import java.io.FileReader;
044import java.io.IOException;
045import java.io.Reader;
046
047import com.unboundid.util.NotMutable;
048import com.unboundid.util.NotNull;
049import com.unboundid.util.Nullable;
050import com.unboundid.util.ThreadSafety;
051import com.unboundid.util.ThreadSafetyLevel;
052
053import static com.unboundid.ldap.sdk.unboundidds.logs.LogMessages.*;
054
055
056
057/**
058 * This class provides a mechanism for reading messages from a Directory Server
059 * access log.
060 * <BR>
061 * <BLOCKQUOTE>
062 *   <B>NOTE:</B>  This class, and other classes within the
063 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
064 *   supported for use against Ping Identity, UnboundID, and
065 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
066 *   for proprietary functionality or for external specifications that are not
067 *   considered stable or mature enough to be guaranteed to work in an
068 *   interoperable way with other types of LDAP servers.
069 * </BLOCKQUOTE>
070 */
071@NotMutable()
072@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
073public final class AccessLogReader
074       implements Closeable
075{
076  // The reader used to read the contents of the log file.
077  @NotNull private final BufferedReader reader;
078
079
080
081  /**
082   * Creates a new access log reader that will read messages from the specified
083   * log file.
084   *
085   * @param  path  The path of the log file to read.
086   *
087   * @throws  IOException  If a problem occurs while opening the file for
088   *                       reading.
089   */
090  public AccessLogReader(@NotNull final String path)
091         throws IOException
092  {
093    reader = new BufferedReader(new FileReader(path));
094  }
095
096
097
098  /**
099   * Creates a new access log reader that will read messages from the specified
100   * log file.
101   *
102   * @param  file  The log file to read.
103   *
104   * @throws  IOException  If a problem occurs while opening the file for
105   *                       reading.
106   */
107  public AccessLogReader(@NotNull final File file)
108         throws IOException
109  {
110    reader = new BufferedReader(new FileReader(file));
111  }
112
113
114
115  /**
116   * Creates a new access log reader that will read messages using the provided
117   * {@code Reader} object.
118   *
119   * @param  reader  The reader to use to read log messages.
120   */
121  public AccessLogReader(@NotNull final Reader reader)
122  {
123    if (reader instanceof BufferedReader)
124    {
125      this.reader = (BufferedReader) reader;
126    }
127    else
128    {
129      this.reader = new BufferedReader(reader);
130    }
131  }
132
133
134
135  /**
136   * Reads the next access log message from the log file.
137   *
138   * @return  The access log message read from the log file, or {@code null} if
139   *          there are no more messages to be read.
140   *
141   * @throws  IOException  If an error occurs while trying to read from the
142   *                       file.
143   *
144   * @throws  LogException  If an error occurs while trying to parse the log
145   *                        message.
146   */
147  @Nullable()
148  public AccessLogMessage read()
149         throws IOException, LogException
150  {
151    while (true)
152    {
153      final String line = reader.readLine();
154      if (line == null)
155      {
156        return null;
157      }
158
159      if (line.isEmpty() || (line.charAt(0) == '#'))
160      {
161        continue;
162      }
163
164      return parse(line);
165    }
166  }
167
168
169
170  /**
171   * Parses the provided string as an access log message.
172   *
173   * @param  s  The string to parse as an access log message.
174   *
175   * @return  The parsed access log message.
176   *
177   * @throws  LogException  If an error occurs while trying to parse the log
178   *                        message.
179   */
180  @NotNull()
181  public static AccessLogMessage parse(@NotNull final String s)
182         throws LogException
183  {
184    final LogMessage m = new LogMessage(s);
185    if (m.hasUnnamedValue(AccessLogMessageType.CONNECT.getLogIdentifier()))
186    {
187      return new ConnectAccessLogMessage(m);
188    }
189    else if (m.hasUnnamedValue(AccessLogMessageType.DISCONNECT.
190                  getLogIdentifier()))
191    {
192      return new DisconnectAccessLogMessage(m);
193    }
194    else if (m.hasUnnamedValue(AccessLogMessageType.CLIENT_CERTIFICATE.
195                  getLogIdentifier()))
196    {
197      return new ClientCertificateAccessLogMessage(m);
198    }
199    else if (m.hasUnnamedValue(AccessLogMessageType.SECURITY_NEGOTIATION.
200                  getLogIdentifier()))
201    {
202      return new SecurityNegotiationAccessLogMessage(m);
203    }
204    else if (m.hasUnnamedValue(AccessLogMessageType.ENTRY_REBALANCING_REQUEST.
205                  getLogIdentifier()))
206    {
207      return new EntryRebalancingRequestAccessLogMessage(m);
208    }
209    else if (m.hasUnnamedValue(AccessLogMessageType.ENTRY_REBALANCING_RESULT.
210                  getLogIdentifier()))
211    {
212      return new EntryRebalancingResultAccessLogMessage(m);
213    }
214    else if (m.hasUnnamedValue(AccessLogMessageType.REQUEST.
215                  getLogIdentifier()))
216    {
217      if (m.hasUnnamedValue(AccessLogOperationType.ABANDON.
218               getLogIdentifier()))
219      {
220        return new AbandonRequestAccessLogMessage(m);
221      }
222      else if (m.hasUnnamedValue(AccessLogOperationType.ADD.
223                    getLogIdentifier()))
224      {
225        return new AddRequestAccessLogMessage(m);
226      }
227      else if (m.hasUnnamedValue(AccessLogOperationType.BIND.
228                    getLogIdentifier()))
229      {
230        return new BindRequestAccessLogMessage(m);
231      }
232      else if (m.hasUnnamedValue(AccessLogOperationType.COMPARE.
233                    getLogIdentifier()))
234      {
235        return new CompareRequestAccessLogMessage(m);
236      }
237      else if (m.hasUnnamedValue(AccessLogOperationType.DELETE.
238                    getLogIdentifier()))
239      {
240        return new DeleteRequestAccessLogMessage(m);
241      }
242      else if (m.hasUnnamedValue(AccessLogOperationType.EXTENDED.
243                    getLogIdentifier()))
244      {
245        return new ExtendedRequestAccessLogMessage(m);
246      }
247      else if (m.hasUnnamedValue(AccessLogOperationType.MODIFY.
248                    getLogIdentifier()))
249      {
250        return new ModifyRequestAccessLogMessage(m);
251      }
252      else if (m.hasUnnamedValue(AccessLogOperationType.MODDN.
253                    getLogIdentifier()))
254      {
255        return new ModifyDNRequestAccessLogMessage(m);
256      }
257      else if (m.hasUnnamedValue(AccessLogOperationType.SEARCH.
258                    getLogIdentifier()))
259      {
260        return new SearchRequestAccessLogMessage(m);
261      }
262      else if (m.hasUnnamedValue(AccessLogOperationType.UNBIND.
263                    getLogIdentifier()))
264      {
265        return new UnbindRequestAccessLogMessage(m);
266      }
267      else
268      {
269        throw new LogException(s,
270             ERR_LOG_MESSAGE_INVALID_REQUEST_OPERATION_TYPE.get());
271      }
272    }
273    else if (m.hasUnnamedValue(AccessLogMessageType.RESULT.
274                  getLogIdentifier()))
275    {
276      if (m.hasUnnamedValue(AccessLogOperationType.ABANDON.
277               getLogIdentifier()))
278      {
279        return new AbandonResultAccessLogMessage(m);
280      }
281      else if (m.hasUnnamedValue(AccessLogOperationType.ADD.
282                    getLogIdentifier()))
283      {
284        return new AddResultAccessLogMessage(m);
285      }
286      else if (m.hasUnnamedValue(AccessLogOperationType.BIND.
287                    getLogIdentifier()))
288      {
289        return new BindResultAccessLogMessage(m);
290      }
291      else if (m.hasUnnamedValue(AccessLogOperationType.COMPARE.
292                    getLogIdentifier()))
293      {
294        return new CompareResultAccessLogMessage(m);
295      }
296      else if (m.hasUnnamedValue(AccessLogOperationType.DELETE.
297                    getLogIdentifier()))
298      {
299        return new DeleteResultAccessLogMessage(m);
300      }
301      else if (m.hasUnnamedValue(AccessLogOperationType.EXTENDED.
302                    getLogIdentifier()))
303      {
304        return new ExtendedResultAccessLogMessage(m);
305      }
306      else if (m.hasUnnamedValue(AccessLogOperationType.MODIFY.
307                    getLogIdentifier()))
308      {
309        return new ModifyResultAccessLogMessage(m);
310      }
311      else if (m.hasUnnamedValue(AccessLogOperationType.MODDN.
312                    getLogIdentifier()))
313      {
314        return new ModifyDNResultAccessLogMessage(m);
315      }
316      else if (m.hasUnnamedValue(AccessLogOperationType.SEARCH.
317                    getLogIdentifier()))
318      {
319        return new SearchResultAccessLogMessage(m);
320      }
321      else
322      {
323        throw new LogException(s,
324             ERR_LOG_MESSAGE_INVALID_RESULT_OPERATION_TYPE.get());
325      }
326    }
327    else if (m.hasUnnamedValue(AccessLogMessageType.FORWARD.
328                  getLogIdentifier()))
329    {
330      if (m.hasUnnamedValue(AccessLogOperationType.ABANDON.
331               getLogIdentifier()))
332      {
333        return new AbandonForwardAccessLogMessage(m);
334      }
335      else if (m.hasUnnamedValue(AccessLogOperationType.ADD.
336                    getLogIdentifier()))
337      {
338        return new AddForwardAccessLogMessage(m);
339      }
340      else if (m.hasUnnamedValue(AccessLogOperationType.BIND.
341                    getLogIdentifier()))
342      {
343        return new BindForwardAccessLogMessage(m);
344      }
345      else if (m.hasUnnamedValue(AccessLogOperationType.COMPARE.
346                    getLogIdentifier()))
347      {
348        return new CompareForwardAccessLogMessage(m);
349      }
350      else if (m.hasUnnamedValue(AccessLogOperationType.DELETE.
351                    getLogIdentifier()))
352      {
353        return new DeleteForwardAccessLogMessage(m);
354      }
355      else if (m.hasUnnamedValue(AccessLogOperationType.EXTENDED.
356                    getLogIdentifier()))
357      {
358        return new ExtendedForwardAccessLogMessage(m);
359      }
360      else if (m.hasUnnamedValue(AccessLogOperationType.MODIFY.
361                    getLogIdentifier()))
362      {
363        return new ModifyForwardAccessLogMessage(m);
364      }
365      else if (m.hasUnnamedValue(AccessLogOperationType.MODDN.
366                    getLogIdentifier()))
367      {
368        return new ModifyDNForwardAccessLogMessage(m);
369      }
370      else if (m.hasUnnamedValue(AccessLogOperationType.SEARCH.
371                    getLogIdentifier()))
372      {
373        return new SearchForwardAccessLogMessage(m);
374      }
375      else
376      {
377        throw new LogException(s,
378             ERR_LOG_MESSAGE_INVALID_FORWARD_OPERATION_TYPE.get());
379      }
380    }
381    else if (m.hasUnnamedValue(AccessLogMessageType.FORWARD_FAILED.
382                  getLogIdentifier()))
383    {
384      if (m.hasUnnamedValue(AccessLogOperationType.ADD.getLogIdentifier()))
385      {
386        return new AddForwardFailedAccessLogMessage(m);
387      }
388      else if (m.hasUnnamedValue(AccessLogOperationType.BIND.
389                    getLogIdentifier()))
390      {
391        return new BindForwardFailedAccessLogMessage(m);
392      }
393      else if (m.hasUnnamedValue(AccessLogOperationType.COMPARE.
394                    getLogIdentifier()))
395      {
396        return new CompareForwardFailedAccessLogMessage(m);
397      }
398      else if (m.hasUnnamedValue(AccessLogOperationType.DELETE.
399                    getLogIdentifier()))
400      {
401        return new DeleteForwardFailedAccessLogMessage(m);
402      }
403      else if (m.hasUnnamedValue(AccessLogOperationType.EXTENDED.
404                    getLogIdentifier()))
405      {
406        return new ExtendedForwardFailedAccessLogMessage(m);
407      }
408      else if (m.hasUnnamedValue(AccessLogOperationType.MODIFY.
409                    getLogIdentifier()))
410      {
411        return new ModifyForwardFailedAccessLogMessage(m);
412      }
413      else if (m.hasUnnamedValue(AccessLogOperationType.MODDN.
414                    getLogIdentifier()))
415      {
416        return new ModifyDNForwardFailedAccessLogMessage(m);
417      }
418      else if (m.hasUnnamedValue(AccessLogOperationType.SEARCH.
419                    getLogIdentifier()))
420      {
421        return new SearchForwardFailedAccessLogMessage(m);
422      }
423      else
424      {
425        throw new LogException(s,
426             ERR_LOG_MESSAGE_INVALID_FORWARD_FAILED_OPERATION_TYPE.get());
427      }
428    }
429    else if (m.hasUnnamedValue(AccessLogMessageType.ASSURANCE_COMPLETE.
430                  getLogIdentifier()))
431    {
432      if (m.hasUnnamedValue(AccessLogOperationType.ADD.getLogIdentifier()))
433      {
434        return new AddAssuranceCompletedAccessLogMessage(m);
435      }
436      else if (m.hasUnnamedValue(AccessLogOperationType.DELETE.
437                    getLogIdentifier()))
438      {
439        return new DeleteAssuranceCompletedAccessLogMessage(m);
440      }
441      else if (m.hasUnnamedValue(AccessLogOperationType.MODIFY.
442                    getLogIdentifier()))
443      {
444        return new ModifyAssuranceCompletedAccessLogMessage(m);
445      }
446      else if (m.hasUnnamedValue(AccessLogOperationType.MODDN.
447                    getLogIdentifier()))
448      {
449        return new ModifyDNAssuranceCompletedAccessLogMessage(m);
450      }
451      else
452      {
453        throw new LogException(s,
454             ERR_LOG_MESSAGE_INVALID_ASSURANCE_COMPLETE_OPERATION_TYPE.get());
455      }
456    }
457    else if (m.hasUnnamedValue(AccessLogMessageType.ENTRY.getLogIdentifier()))
458    {
459      return new SearchEntryAccessLogMessage(m);
460    }
461    else if (m.hasUnnamedValue(AccessLogMessageType.REFERENCE.
462                  getLogIdentifier()))
463    {
464      return new SearchReferenceAccessLogMessage(m);
465    }
466    else if (m.hasUnnamedValue(AccessLogMessageType.INTERMEDIATE_RESPONSE.
467                  getLogIdentifier()))
468    {
469      return new IntermediateResponseAccessLogMessage(m);
470    }
471    else
472    {
473      throw new LogException(s,
474           ERR_LOG_MESSAGE_INVALID_ACCESS_MESSAGE_TYPE.get());
475    }
476  }
477
478
479
480  /**
481   * Closes this error log reader.
482   *
483   * @throws  IOException  If a problem occurs while closing the reader.
484   */
485  @Override()
486  public void close()
487         throws IOException
488  {
489    reader.close();
490  }
491}