001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2012-2015 ForgeRock AS
026 */
027package org.opends.server.types;
028
029import static org.opends.messages.UtilityMessages.*;
030
031import java.io.*;
032import java.util.*;
033import java.util.zip.GZIPInputStream;
034
035import org.forgerock.i18n.LocalizableMessageDescriptor.Arg1;
036import org.opends.server.tools.makeldif.MakeLDIFInputStream;
037import org.opends.server.tools.makeldif.TemplateFile;
038import org.opends.server.util.CollectionUtils;
039import org.opends.server.util.StaticUtils;
040
041/**
042 * This class defines a data structure for holding configuration
043 * information to use when performing an LDIF import.
044 */
045@org.opends.server.types.PublicAPI(
046     stability=org.opends.server.types.StabilityLevel.VOLATILE,
047     mayInstantiate=true,
048     mayExtend=false,
049     mayInvoke=true)
050public final class LDIFImportConfig extends OperationConfig
051                                    implements Closeable
052{
053
054  /** The default buffer size that will be used when reading LDIF data. */
055  private static final int DEFAULT_BUFFER_SIZE = 8192;
056
057  /**
058   * Indicates whether to append to the existing data set rather than
059   * replacing it.
060   */
061  private boolean appendToExistingData;
062
063  /**
064   * Indicates whether to include the objectclasses in the entries
065   * read from the import.
066   */
067  private boolean includeObjectClasses = true;
068
069  /** Indicates whether to invoke LDIF import plugins whenever an entry is read. */
070  private boolean invokeImportPlugins;
071  /** Indicates whether the import is compressed. */
072  private boolean isCompressed;
073  /** Indicates whether the import is encrypted. */
074  private boolean isEncrypted;
075  /** Indicates whether to clear all base DNs in a backend. */
076  private boolean clearBackend;
077  /** Indicates whether to replace existing entries when appending data. */
078  private boolean replaceExistingEntries;
079  /** Indicates whether to perform schema validation on the entries read. */
080  private boolean validateSchema = true;
081
082  /** The buffered reader from which the LDIF data should be read. */
083  private BufferedReader reader;
084  /** The buffered writer to which rejected entries should be written. */
085  private BufferedWriter rejectWriter;
086  /** The buffered writer to which rejected entries should be written. */
087  private BufferedWriter skipWriter;
088  /** The input stream to use to read the data to import. */
089  private InputStream ldifInputStream;
090
091  /** The buffer size to use when reading data from the LDIF file. */
092  private int bufferSize = DEFAULT_BUFFER_SIZE;
093
094  /** The iterator used to read through the set of LDIF files. */
095  private Iterator<String> ldifFileIterator;
096
097  /** The set of base DNs to exclude from the import. */
098  private Set<DN> excludeBranches = new HashSet<>(0);
099  /** The set of base DNs to include from the import. */
100  private Set<DN> includeBranches = new HashSet<>(0);
101
102  /** The set of search filters for entries to exclude from the import. */
103  private List<SearchFilter> excludeFilters = new ArrayList<>(0);
104  /** The set of search filters for entries to include in the import. */
105  private List<SearchFilter> includeFilters = new ArrayList<>(0);
106
107  /** The set of LDIF files to be imported. */
108  private List<String> ldifFiles;
109
110  /** The set of attribute types that should be excluded from the import. */
111  private Set<AttributeType> excludeAttributes = new HashSet<>(0);
112  /** The set of attribute types that should be included in the import. */
113  private Set<AttributeType> includeAttributes = new HashSet<>(0);
114
115  /** Indicates whether all the user attributes should be included. */
116  private boolean includeAllUserAttrs;
117  /** Indicates whether all the operational attributes should be included. */
118  private boolean includeAllOpAttrs;
119  /** Indicates whether all the user attributes should be excluded. */
120  private boolean excludeAllUserAttrs;
121  /** Indicates whether all the operational attributes should be excluded. */
122  private boolean excludeAllOpAttrs;
123
124  private String tmpDirectory;
125  private boolean skipDNValidation;
126  private int threadCount;
127
128
129  /**
130   * Creates a new LDIF import configuration that will read from the
131   * specified LDIF file.
132   *
133   * @param  ldifFile  The path to the LDIF file with the data to
134   *                   import.
135   */
136  public LDIFImportConfig(String ldifFile)
137  {
138    ldifFiles = CollectionUtils.newArrayList(ldifFile);
139    ldifFileIterator = ldifFiles.iterator();
140  }
141
142  /**
143   * Creates a new LDIF import configuration that will read from the
144   * specified LDIF files.  The files will be imported in the order
145   * they are specified in the provided list.
146   *
147   * @param  ldifFiles  The paths to the LDIF files with the data to
148   *                    import.
149   */
150  public LDIFImportConfig(List<String> ldifFiles)
151  {
152    this.ldifFiles = ldifFiles;
153    ldifFileIterator = ldifFiles.iterator();
154  }
155
156  /**
157   * Creates a new LDIF import configuration that will read from the
158   * provided input stream.
159   *
160   * @param  ldifInputStream  The input stream from which to read the
161   *                          LDIF data.
162   */
163  public LDIFImportConfig(InputStream ldifInputStream)
164  {
165    this.ldifInputStream   = ldifInputStream;
166  }
167
168  /**
169   * Creates a new LDIF import configuration that will read from the
170   * provided reader.
171   *
172   * @param  ldifInputReader  The input stream from which to read the
173   *                          LDIF data.
174   */
175  public LDIFImportConfig(Reader ldifInputReader)
176  {
177    reader                 = getBufferedReader(ldifInputReader);
178  }
179
180  /**
181   * Wrap reader in a BufferedReader if necessary.
182   *
183   * @param reader the reader to buffer
184   * @return reader as a BufferedReader
185   */
186  private BufferedReader getBufferedReader(Reader reader) {
187    if (reader instanceof BufferedReader) {
188      return (BufferedReader)reader;
189    } else {
190      return new BufferedReader(reader);
191    }
192  }
193
194  /**
195   * Creates a new LDIF import configuration that will generate
196   * entries using the given MakeLDIF template file rather than
197   * reading them from an existing LDIF file.
198   *
199   * @param  templateFile  The template file to use to generate the
200   *                       entries.
201   */
202  public LDIFImportConfig(TemplateFile templateFile)
203  {
204    this(new MakeLDIFInputStream(templateFile));
205  }
206
207
208
209  /**
210   * Retrieves the reader that should be used to read the LDIF data.
211   * Note that if the LDIF file is compressed and/or encrypted, then
212   * that must be indicated before this method is called for the first
213   * time.
214   *
215   * @return  The reader that should be used to read the LDIF data.
216   *
217   * @throws  IOException  If a problem occurs while obtaining the
218   *                       reader.
219   */
220  public BufferedReader getReader()
221         throws IOException
222  {
223    if (reader == null)
224    {
225      InputStream inputStream;
226      if (ldifInputStream != null)
227      {
228        inputStream = ldifInputStream;
229      }
230      else
231      {
232        inputStream = ldifInputStream =
233             new FileInputStream(ldifFileIterator.next());
234      }
235
236      if (isEncrypted)
237      {
238        // FIXME -- Add support for encryption with a cipher input
239        //          stream.
240      }
241
242      if (isCompressed)
243      {
244        inputStream = new GZIPInputStream(inputStream);
245      }
246
247      reader = new BufferedReader(new InputStreamReader(inputStream),
248                                  bufferSize);
249    }
250
251    return reader;
252  }
253
254
255
256  /**
257   * Retrieves the LDIF reader configured to read from the next LDIF
258   * file in the list.
259   *
260   * @return  The reader that should be used to read the LDIF data, or
261   *          <CODE>null</CODE> if there are no more files to read.
262   *
263   * @throws  IOException  If a problem occurs while obtaining the reader.
264   */
265  public BufferedReader nextReader()
266         throws IOException
267  {
268    if (ldifFileIterator == null || !ldifFileIterator.hasNext())
269    {
270      return null;
271    }
272
273    reader.close();
274
275    InputStream inputStream = ldifInputStream =
276         new FileInputStream(ldifFileIterator.next());
277
278    if (isEncrypted)
279    {
280      // FIXME -- Add support for encryption with a cipher input stream.
281    }
282
283    if (isCompressed)
284    {
285      inputStream = new GZIPInputStream(inputStream);
286    }
287
288    reader = new BufferedReader(new InputStreamReader(inputStream), bufferSize);
289    return reader;
290  }
291
292
293
294  /**
295   * Retrieves the writer that should be used to write entries that
296   * are rejected rather than imported for some reason.
297   *
298   * @return  The reject writer, or <CODE>null</CODE> if none is to be used.
299   */
300  public BufferedWriter getRejectWriter()
301  {
302    return rejectWriter;
303  }
304
305  /**
306   * Retrieves the writer that should be used to write entries that
307   * are skipped because they don't match the criteria.
308   *
309   * @return  The skip writer, or <CODE>null</CODE> if none is to be used.
310   */
311  public BufferedWriter getSkipWriter()
312  {
313    return skipWriter;
314  }
315
316  /**
317   * Indicates that rejected entries should be written to the
318   * specified file.  Note that this applies only to entries that are
319   * rejected because they are invalid (e.g., are malformed or don't
320   * conform to schema requirements), and not to entries that are
321   * rejected because they matched exclude criteria.
322   *
323   * @param  rejectFile            The path to the file to which
324   *                               reject information should be written.
325   * @param  existingFileBehavior  Indicates how to treat an existing file.
326   *
327   * @throws  IOException  If a problem occurs while opening the
328   *                       reject file for writing.
329   */
330  public void writeRejectedEntries(String rejectFile,
331                   ExistingFileBehavior existingFileBehavior)
332         throws IOException
333  {
334    if (rejectFile == null)
335    {
336      closeRejectWriter();
337      return;
338    }
339
340    final BufferedWriter writer = newBufferedWriter(rejectFile, existingFileBehavior, ERR_REJECT_FILE_EXISTS);
341    if (writer != null)
342    {
343      rejectWriter = writer;
344    }
345  }
346
347  private BufferedWriter newBufferedWriter(String file, ExistingFileBehavior existingFileBehavior,
348      Arg1<Object> fileExistsErrorMsg) throws IOException
349  {
350    switch (existingFileBehavior)
351    {
352    case APPEND:
353      return new BufferedWriter(new FileWriter(file, true));
354    case OVERWRITE:
355      return new BufferedWriter(new FileWriter(file, false));
356    case FAIL:
357      File f = new File(file);
358      if (f.exists())
359      {
360        throw new IOException(fileExistsErrorMsg.get(file).toString());
361      }
362      return new BufferedWriter(new FileWriter(file));
363    default:
364      return null;
365    }
366  }
367
368  /**
369   * Indicates that rejected entries should be written to the provided
370   * output stream.  Note that this applies only to entries that are
371   * rejected because they are invalid (e.g., are malformed or don't
372   * conform to schema requirements), and not to entries that are
373   * rejected because they matched exclude criteria.
374   *
375   * @param  outputStream  The output stream to which rejected entries
376   *                       should be written.
377   */
378  public void writeRejectedEntries(OutputStream outputStream)
379  {
380    if (outputStream == null)
381    {
382      closeRejectWriter();
383      return;
384    }
385
386    rejectWriter =
387         new BufferedWriter(new OutputStreamWriter(outputStream));
388  }
389
390  private void closeRejectWriter()
391  {
392    if (rejectWriter != null)
393    {
394      StaticUtils.close(rejectWriter);
395      rejectWriter = null;
396    }
397  }
398
399  /**
400   * Indicates that skipped entries should be written to the
401   * specified file.  Note that this applies only to entries that are
402   * skipped because they matched exclude criteria.
403   *
404   * @param  skipFile              The path to the file to which
405   *                               skipped information should be written.
406   * @param  existingFileBehavior  Indicates how to treat an existing file.
407   *
408   * @throws  IOException  If a problem occurs while opening the
409   *                       skip file for writing.
410   */
411  public void writeSkippedEntries(String skipFile,
412                   ExistingFileBehavior existingFileBehavior)
413         throws IOException
414  {
415    if (skipFile == null)
416    {
417      closeSkipWriter();
418      return;
419    }
420
421    final BufferedWriter writer = newBufferedWriter(skipFile, existingFileBehavior, ERR_SKIP_FILE_EXISTS);
422    if (writer != null)
423    {
424      skipWriter = writer;
425    }
426  }
427
428  private void closeSkipWriter()
429  {
430    if (skipWriter != null)
431    {
432      StaticUtils.close(skipWriter);
433      skipWriter = null;
434    }
435  }
436
437  /**
438   * Indicates that skipped entries should be written to the provided
439   * output stream.  Note that this does not apply to entries that are
440   * rejected because they are invalid (e.g., are malformed or don't
441   * conform to schema requirements), but only apply to entries that
442   * are skipped because they matched exclude criteria.
443   *
444   * @param  outputStream  The output stream to which skipped entries
445   *                       should be written.
446   */
447  public void writeSkippedEntries(OutputStream outputStream)
448  {
449    if (outputStream == null)
450    {
451      closeSkipWriter();
452      return;
453    }
454    skipWriter =
455         new BufferedWriter(new OutputStreamWriter(outputStream));
456  }
457
458  /**
459   * Indicates whether to append to an existing data set or completely
460   * replace it.
461   *
462   * @return  <CODE>true</CODE> if the import should append to an
463   *          existing data set, or <CODE>false</CODE> if not.
464   */
465  public boolean appendToExistingData()
466  {
467    return appendToExistingData;
468  }
469
470
471
472  /**
473   * Specifies whether to append to an existing data set or completely
474   * replace it.
475   *
476   * @param  appendToExistingData  Indicates whether to append to an
477   *                               existing data set or completely
478   *                               replace it.
479   */
480  public void setAppendToExistingData(boolean appendToExistingData)
481  {
482    this.appendToExistingData = appendToExistingData;
483  }
484
485
486
487  /**
488   * Indicates whether to replace the existing entry if a duplicate is
489   * found or to reject the new entry.  This only applies when
490   * appending to an existing data set.
491   *
492   * @return  <CODE>true</CODE> if an existing entry should be
493   *          replaced with the new entry from the provided data set,
494   *          or <CODE>false</CODE> if the new entry should be
495   *          rejected.
496   */
497  public boolean replaceExistingEntries()
498  {
499    return replaceExistingEntries;
500  }
501
502
503
504  /**
505   * Specifies whether to replace the existing entry if a duplicate is
506   * found or to reject the new entry.  This only applies when
507   * appending to an existing data set.
508   *
509   * @param  replaceExistingEntries  Indicates whether to replace the
510   *                                 existing entry if a duplicate is
511   *                                 found or to reject the new entry.
512   */
513  public void setReplaceExistingEntries(boolean replaceExistingEntries)
514  {
515    this.replaceExistingEntries = replaceExistingEntries;
516  }
517
518
519
520  /**
521   * Indicates whether any LDIF import plugins registered with the
522   * server should be invoked during the import operation.
523   *
524   * @return  <CODE>true</CODE> if registered LDIF import plugins
525   *          should be invoked during the import operation, or
526   *          <CODE>false</CODE> if they should not be invoked.
527   */
528  public boolean invokeImportPlugins()
529  {
530    return invokeImportPlugins;
531  }
532
533
534
535  /**
536   * Specifies whether any LDIF import plugins registered with the
537   * server should be invoked during the import operation.
538   *
539   * @param  invokeImportPlugins  Specifies whether any LDIF import
540   *                              plugins registered with the server
541   *                              should be invoked during the import
542   *                              operation.
543   */
544  public void setInvokeImportPlugins(boolean invokeImportPlugins)
545  {
546    this.invokeImportPlugins = invokeImportPlugins;
547  }
548
549
550
551  /**
552   * Indicates whether the input LDIF source is expected to be
553   * compressed.
554   *
555   * @return  <CODE>true</CODE> if the LDIF source is expected to be
556   *          compressed, or <CODE>false</CODE> if not.
557   */
558  public boolean isCompressed()
559  {
560    return isCompressed;
561  }
562
563
564
565  /**
566   * Specifies whether the input LDIF source is expected to be
567   * compressed.  If compression is used, then this must be set prior
568   * to the initial call to <CODE>getReader</CODE>.
569   *
570   * @param  isCompressed  Indicates whether the input LDIF source is
571   *                       expected to be compressed.
572   */
573  public void setCompressed(boolean isCompressed)
574  {
575    this.isCompressed = isCompressed;
576  }
577
578
579
580  /**
581   * Indicates whether the input LDIF source is expected to be
582   * encrypted.
583   *
584   * @return  <CODE>true</CODE> if the LDIF source is expected to be
585   *          encrypted, or <CODE>false</CODE> if not.
586   */
587  public boolean isEncrypted()
588  {
589    return isEncrypted;
590  }
591
592
593
594  /**
595   * Specifies whether the input LDIF source is expected to be
596   * encrypted.  If encryption is used, then this must be set prior to
597   * the initial call to <CODE>getReader</CODE>.
598   *
599   * @param  isEncrypted  Indicates whether the input LDIF source is
600   *                      expected to be encrypted.
601   */
602  public void setEncrypted(boolean isEncrypted)
603  {
604    this.isEncrypted = isEncrypted;
605  }
606
607
608
609  /**
610   * Indicates whether to clear the entire backend if importing to a
611   * backend with more than one base DNs.
612   *
613   * @return <CODE>true</code> if the entire backend should be
614   * cleared or <CODE>false</CODE> if not.
615   */
616  public boolean clearBackend()
617  {
618    return clearBackend;
619  }
620
621
622
623  /**
624   * Specifies whether to clear the entire backend if importing to a
625   * backend.
626   *
627   * @param clearBackend Indicates whether to clear the entire
628   * backend.
629   */
630  public void setClearBackend(boolean clearBackend)
631  {
632    this.clearBackend = clearBackend;
633  }
634
635
636
637  /**
638   * Indicates whether to perform schema validation on entries as they
639   * are read.
640   *
641   * @return  <CODE>true</CODE> if schema validation should be
642   *          performed on the entries as they are read, or
643   *          <CODE>false</CODE> if not.
644   */
645  public boolean validateSchema()
646  {
647    return validateSchema;
648  }
649
650
651
652  /**
653   * Specifies whether to perform schema validation on entries as they
654   * are read.
655   *
656   * @param  validateSchema  Indicates whether to perform schema
657   *                         validation on entries as they are read.
658   */
659  public void setValidateSchema(boolean validateSchema)
660  {
661    this.validateSchema = validateSchema;
662  }
663
664
665
666  /**
667   * Retrieves the set of base DNs that specify the set of entries to
668   * exclude from the import.  The contents of the returned list may
669   * be altered by the caller.
670   *
671   * @return  The set of base DNs that specify the set of entries to
672   *          exclude from the import.
673   */
674  public Set<DN> getExcludeBranches()
675  {
676    return excludeBranches;
677  }
678
679
680
681  /**
682   * Specifies the set of base DNs that specify the set of entries to
683   * exclude from the import.
684   *
685   * @param  excludeBranches  The set of base DNs that specify the set
686   *                          of entries to exclude from the import.
687   */
688  public void setExcludeBranches(Set<DN> excludeBranches)
689  {
690    this.excludeBranches = getSet(excludeBranches);
691  }
692
693  private <T> Set<T> getSet(Set<T> set)
694  {
695    return set != null ? set : new HashSet<T>(0);
696  }
697
698
699  /**
700   * Retrieves the set of base DNs that specify the set of entries to
701   * include in the import.  The contents of the returned list may be
702   * altered by the caller.
703   *
704   * @return  The set of base DNs that specify the set of entries to
705   *          include in the import.
706   */
707  public Set<DN> getIncludeBranches()
708  {
709    return includeBranches;
710  }
711
712
713
714  /**
715   * Specifies the set of base DNs that specify the set of entries to
716   * include in the import.
717   *
718   * @param  includeBranches  The set of base DNs that specify the set
719   *                          of entries to include in the import.
720   */
721  public void setIncludeBranches(Set<DN> includeBranches)
722  {
723    this.includeBranches = getSet(includeBranches);
724  }
725
726  /**
727   * Indicates whether to include the entry with the specified DN in
728   * the import.
729   *
730   * @param  dn  The DN of the entry for which to make the
731   *             determination.
732   *
733   * @return  <CODE>true</CODE> if the entry with the specified DN
734   *          should be included in the import, or <CODE>false</CODE>
735   *          if not.
736   */
737  public boolean includeEntry(DN dn)
738  {
739    if (! excludeBranches.isEmpty())
740    {
741      for (DN excludeBranch : excludeBranches)
742      {
743        if (excludeBranch.isAncestorOf(dn))
744        {
745          return false;
746        }
747      }
748    }
749
750    if (! includeBranches.isEmpty())
751    {
752      for (DN includeBranch : includeBranches)
753      {
754        if (includeBranch.isAncestorOf(dn))
755        {
756          return true;
757        }
758      }
759
760      return false;
761    }
762
763    return true;
764  }
765
766
767
768  /**
769   * Indicates whether the set of objectclasses should be included in
770   * the entries read from the LDIF.
771   *
772   * @return  <CODE>true</CODE> if the set of objectclasses should be
773   *          included in the entries read from the LDIF, or
774   *          <CODE>false</CODE> if not.
775   */
776  public boolean includeObjectClasses()
777  {
778    return includeObjectClasses;
779  }
780
781
782
783  /**
784   * Specifies whether the set of objectclasses should be included in
785   * the entries read from the LDIF.
786   *
787   * @param  includeObjectClasses  Indicates whether the set of
788   *                               objectclasses should be included in
789   *                               the entries read from the LDIF.
790   */
791  public void setIncludeObjectClasses(boolean includeObjectClasses)
792  {
793    this.includeObjectClasses = includeObjectClasses;
794  }
795
796
797
798  /**
799   * Retrieves the set of attributes that should be excluded from the
800   * entries read from the LDIF.  The contents of the returned set may
801   * be modified by the caller.
802   *
803   * @return  The set of attributes that should be excluded from the
804   *          entries read from the LDIF.
805   */
806  public Set<AttributeType> getExcludeAttributes()
807  {
808    return excludeAttributes;
809  }
810
811
812
813  /**
814   * Specifies the set of attributes that should be excluded from the
815   * entries read from the LDIF.
816   *
817   * @param  excludeAttributes  The set of attributes that should be
818   *                            excluded from the entries read from
819   *                            the LDIF.
820   */
821  public void setExcludeAttributes(Set<AttributeType> excludeAttributes)
822  {
823    this.excludeAttributes = getSet(excludeAttributes);
824  }
825
826  /**
827   * Retrieves the set of attributes that should be included in the
828   * entries read from the LDIF.  The contents of the returned set may
829   * be modified by the caller.
830   *
831   * @return  The set of attributes that should be included in the
832   *          entries read from the LDIF.
833   */
834  public Set<AttributeType> getIncludeAttributes()
835  {
836    return includeAttributes;
837  }
838
839
840
841  /**
842   * Specifies the set of attributes that should be included in the
843   * entries read from the LDIF.
844   *
845   * @param  includeAttributes  The set of attributes that should be
846   *                            included in the entries read from the
847   *                            LDIF.
848   */
849  public void setIncludeAttributes(Set<AttributeType> includeAttributes)
850  {
851    this.includeAttributes = getSet(includeAttributes);
852  }
853
854  /**
855   * Indicates whether the specified attribute should be included in
856   * the entries read from the LDIF.
857   *
858   * @param  attributeType  The attribute type for which to make the
859   *                        determination.
860   *
861   * @return  <CODE>true</CODE> if the specified attribute should be
862   *          included in the entries read from the LDIF, or
863   *         <CODE>false</CODE> if not.
864   */
865  public boolean includeAttribute(AttributeType attributeType)
866  {
867    if (!excludeAttributes.isEmpty()
868        && excludeAttributes.contains(attributeType))
869    {
870      return false;
871    }
872
873     if((excludeAllOpAttrs && attributeType.isOperational())
874         || (excludeAllUserAttrs && !attributeType.isOperational()))
875    {
876      return false;
877    }
878
879    if((includeAllUserAttrs && !attributeType.isOperational())
880        || (includeAllOpAttrs && attributeType.isOperational()))
881    {
882      return true;
883    }
884
885    if (! includeAttributes.isEmpty())
886    {
887      return includeAttributes.contains(attributeType);
888    }
889    else if((includeAllUserAttrs && attributeType.isOperational())
890        || (includeAllOpAttrs && !attributeType.isOperational()))
891    {
892      return false;
893    }
894    return true;
895  }
896
897
898
899  /**
900   * Retrieves the set of search filters that should be used to
901   * determine which entries to exclude from the LDIF.  The contents
902   * of the returned list may be modified by the caller.
903   *
904   * @return  The set of search filters that should be used to
905   *          determine which entries to exclude from the LDIF.
906   */
907  public List<SearchFilter> getExcludeFilters()
908  {
909    return excludeFilters;
910  }
911
912
913
914  /**
915   * Specifies the set of search filters that should be used to
916   * determine which entries to exclude from the LDIF.
917   *
918   * @param  excludeFilters  The set of search filters that should be
919   *                         used to determine which entries to
920   *                         exclude from the LDIF.
921   */
922  public void setExcludeFilters(List<SearchFilter> excludeFilters)
923  {
924    this.excludeFilters = getList(excludeFilters);
925  }
926
927  /**
928   * Retrieves the set of search filters that should be used to
929   * determine which entries to include in the LDIF.  The contents of
930   * the returned list may be modified by  the caller.
931   *
932   * @return  The set of search filters that should be used to
933   *          determine which entries to include in the LDIF.
934   */
935  public List<SearchFilter> getIncludeFilters()
936  {
937    return includeFilters;
938  }
939
940
941
942  /**
943   * Specifies the set of search filters that should be used to
944   * determine which entries to include in the LDIF.
945   *
946   * @param  includeFilters  The set of search filters that should be
947   *                         used to determine which entries to
948   *                         include in the LDIF.
949   */
950  public void setIncludeFilters(List<SearchFilter> includeFilters)
951  {
952    this.includeFilters = getList(includeFilters);
953  }
954
955  private <T> List<T> getList(List<T> list)
956  {
957    return list != null ? list : new ArrayList<T>(0);
958  }
959
960  /**
961   * Indicates whether the specified entry should be included in the
962   * import based on the configured set of include and exclude
963   * filters.
964   *
965   * @param  entry  The entry for which to make the determination.
966   *
967   * @return  <CODE>true</CODE> if the specified entry should be
968   *          included in the import, or <CODE>false</CODE> if not.
969   *
970   * @throws  DirectoryException  If there is a problem with any of
971   *                              the search filters used to make the
972   *                              determination.
973   */
974  public boolean includeEntry(Entry entry)
975         throws DirectoryException
976  {
977    if (! excludeFilters.isEmpty())
978    {
979      for (SearchFilter filter : excludeFilters)
980      {
981        if (filter.matchesEntry(entry))
982        {
983          return false;
984        }
985      }
986    }
987
988    if (! includeFilters.isEmpty())
989    {
990      for (SearchFilter filter : includeFilters)
991      {
992        if (filter.matchesEntry(entry))
993        {
994          return true;
995        }
996      }
997
998      return false;
999    }
1000
1001    return true;
1002  }
1003
1004
1005
1006  /**
1007   * Retrieves the buffer size that should be used when reading LDIF
1008   * data.
1009   *
1010   * @return  The buffer size that should be used when reading LDIF
1011   *          data.
1012   */
1013  public int getBufferSize()
1014  {
1015    return bufferSize;
1016  }
1017
1018
1019
1020  /**
1021   * Specifies the buffer size that should be used when reading LDIF
1022   * data.
1023   *
1024   * @param  bufferSize  The buffer size that should be used when
1025   *                     reading LDIF data.
1026   */
1027  public void setBufferSize(int bufferSize)
1028  {
1029    this.bufferSize = bufferSize;
1030  }
1031
1032
1033
1034    /**
1035   * Specifies whether all the user attributes should be excluded.
1036   *
1037   * @param  excludeAllUserAttrs  Specifies all user attributes to
1038   *         be excluded.
1039   */
1040  public void setExcludeAllUserAttributes(boolean excludeAllUserAttrs)
1041  {
1042    this.excludeAllUserAttrs = excludeAllUserAttrs;
1043  }
1044
1045
1046
1047  /**
1048   * Specifies whether all the operational attributes should be
1049   * excluded.
1050   *
1051   * @param  excludeAllOpAttrs  Specifies whether all the
1052   *                            operational attributes
1053   *                            should be excluded.
1054   */
1055  public void setExcludeAllOperationalAttributes(boolean excludeAllOpAttrs)
1056  {
1057    this.excludeAllOpAttrs = excludeAllOpAttrs;
1058  }
1059
1060
1061
1062  /**
1063   * Specifies whether all the operational attributes should be
1064   * included.
1065   *
1066   * @param  includeAllOpAttrs  Specifies whether all
1067   *         the operation attributes should be included.
1068   *
1069   */
1070  public void setIncludeAllOpAttributes(boolean includeAllOpAttrs)
1071  {
1072    this.includeAllOpAttrs = includeAllOpAttrs;
1073  }
1074
1075
1076
1077  /**
1078   * Specifies whether all the user attributes should be included.
1079   *
1080   * @param  includeAllUserAttrs  Specifies whether all the
1081   *                              user attributes should be
1082   *                              included.
1083   */
1084  public void setIncludeAllUserAttributes(boolean includeAllUserAttrs)
1085  {
1086    this.includeAllUserAttrs = includeAllUserAttrs;
1087  }
1088
1089
1090
1091  /** Closes any resources that this import config might have open. */
1092  @Override
1093  public void close()
1094  {
1095    StaticUtils.close(reader, rejectWriter, skipWriter);
1096  }
1097
1098  /**
1099   * Set the temporary directory to the specified path.
1100   *
1101   * @param path The path to set the temporary directory to.
1102   */
1103  public void setTmpDirectory(String path)
1104  {
1105    tmpDirectory = path;
1106  }
1107
1108  /**
1109   * Return the temporary directory path.
1110   *
1111   * @return  The temporary directory string.
1112   */
1113  public String getTmpDirectory()
1114  {
1115    return tmpDirectory;
1116  }
1117
1118  /**
1119   * Set the dn check in phase two boolean to the specified value.
1120   *
1121   * @param v The value to set the dn check in phase two boolean to.
1122   */
1123  public void setSkipDNValidation(boolean v)
1124  {
1125    skipDNValidation = v;
1126  }
1127
1128  /**
1129   * Return the dn check in phase two boolean.
1130   *
1131   * @return Return the dn check in phase two boolean value.
1132   */
1133  public boolean getSkipDNValidation()
1134  {
1135    return skipDNValidation;
1136  }
1137
1138
1139  /**
1140   * Set the thread count.
1141   *
1142   * @param c The thread count value.
1143   */
1144  public void setThreadCount(int c)
1145  {
1146    this.threadCount = c;
1147  }
1148
1149  /**
1150   * Return the specified thread count.
1151   *
1152   * @return The thread count.
1153   */
1154  public int getThreadCount()
1155  {
1156    return this.threadCount;
1157  }
1158}