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