001/*
002 * Copyright 2016-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2016-2017 UnboundID Corp.
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.util;
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.util.concurrent.atomic.AtomicLong;
031
032import com.unboundid.ldap.sdk.Filter;
033import com.unboundid.ldap.sdk.LDAPException;
034import com.unboundid.ldap.sdk.ResultCode;
035
036import static com.unboundid.util.UtilityMessages.*;
037
038
039
040/**
041 * This class provides a mechanism for reading LDAP search filters from a file.
042 * The file is expected to have one filter per line.  Blank lines and lines
043 * beginning with the octothorpe (#) character will be ignored.
044 */
045@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
046public final class FilterFileReader
047       implements Closeable
048{
049  // A counter used to keep track of the line number for information read from
050  // the file.
051  private final AtomicLong lineNumberCounter;
052
053  // The reader to use to read the filters.
054  private final BufferedReader reader;
055
056  // The file from which the filters are being read.
057  private final File filterFile;
058
059
060
061  /**
062   * Creates a new filter file reader that will read from the file with the
063   * specified path.
064   *
065   * @param  path  The path to the file to be read.  It must not be {@code null}
066   *               and the file must exist.
067   *
068   * @throws  IOException  If a problem is encountered while opening the file
069   *                       for reading.
070   */
071  public FilterFileReader(final String path)
072         throws IOException
073  {
074    this(new File(path));
075  }
076
077
078
079  /**
080   * Creates a new filter file reader that will read from the specified file.
081   *
082   * @param  filterFile  The file to be read.  It must not be {@code null} and
083   *                     the file must exist.
084   *
085   * @throws  IOException  If a problem is encountered while opening the file
086   *                       for reading.
087   */
088  public FilterFileReader(final File filterFile)
089         throws IOException
090  {
091    this.filterFile = filterFile;
092
093    reader = new BufferedReader(new FileReader(filterFile));
094    lineNumberCounter = new AtomicLong(0L);
095  }
096
097
098
099  /**
100   * Reads the next filter from the file.
101   *
102   * @return  The filter read from the file, or {@code null} if there are no
103   *          more filters to be read.
104   *
105   * @throws  IOException  If a problem is encountered while trying to read from
106   *                       the file.
107   *
108   * @throws  LDAPException  If data read from the file can't be parsed as an
109   *                         LDAP search filter.
110   */
111  public Filter readFilter()
112         throws IOException, LDAPException
113  {
114    while (true)
115    {
116      final long lineNumber;
117      final String line;
118      synchronized (this)
119      {
120        line = reader.readLine();
121        lineNumber = lineNumberCounter.incrementAndGet();
122      }
123
124      if (line == null)
125      {
126        return null;
127      }
128
129      final String filterString = line.trim();
130      if ((filterString.length() == 0) || filterString.startsWith("#"))
131      {
132        continue;
133      }
134
135      try
136      {
137        return Filter.create(filterString);
138      }
139      catch (final LDAPException le)
140      {
141        Debug.debugException(le);
142        throw new LDAPException(ResultCode.FILTER_ERROR,
143             ERR_FILTER_FILE_READER_CANNOT_PARSE_FILTER.get(filterString,
144                  lineNumber, filterFile.getAbsolutePath(), le.getMessage()),
145             le);
146      }
147    }
148  }
149
150
151
152  /**
153   * Closes this filter file reader.
154   *
155   * @throws  IOException  If a problem is encountered while closing the reader.
156   */
157  public void close()
158         throws IOException
159  {
160    reader.close();
161  }
162}