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