001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2012-2016 ForgeRock AS.
016 */
017package org.opends.server.types;
018
019import static org.opends.messages.UtilityMessages.*;
020
021import java.io.BufferedReader;
022import java.io.BufferedWriter;
023import java.io.Closeable;
024import java.io.File;
025import java.io.FileInputStream;
026import java.io.FileWriter;
027import java.io.IOException;
028import java.io.InputStream;
029import java.io.InputStreamReader;
030import java.io.OutputStream;
031import java.io.OutputStreamWriter;
032import java.io.Reader;
033import java.util.ArrayList;
034import java.util.Collections;
035import java.util.HashSet;
036import java.util.Iterator;
037import java.util.List;
038import java.util.Set;
039import java.util.zip.GZIPInputStream;
040
041import org.forgerock.i18n.LocalizableMessageDescriptor.Arg1;
042import org.forgerock.opendj.ldap.DN;
043import org.forgerock.opendj.ldap.schema.AttributeType;
044import org.opends.server.tools.makeldif.MakeLDIFInputStream;
045import org.opends.server.tools.makeldif.TemplateFile;
046import org.opends.server.util.CollectionUtils;
047import org.opends.server.util.StaticUtils;
048
049/**
050 * This class defines a data structure for holding configuration
051 * information to use when performing an LDIF import.
052 */
053@org.opends.server.types.PublicAPI(
054     stability=org.opends.server.types.StabilityLevel.VOLATILE,
055     mayInstantiate=true,
056     mayExtend=false,
057     mayInvoke=true)
058public final class LDIFImportConfig extends OperationConfig
059                                    implements Closeable
060{
061
062  /** The default buffer size that will be used when reading LDIF data. */
063  private static final int DEFAULT_BUFFER_SIZE = 8192;
064
065  /**
066   * Indicates whether to include the objectclasses in the entries
067   * read from the import.
068   */
069  private boolean includeObjectClasses = true;
070
071  /** Indicates whether to invoke LDIF import plugins whenever an entry is read. */
072  private boolean invokeImportPlugins;
073  /** Indicates whether the import is compressed. */
074  private boolean isCompressed;
075  /** Indicates whether the import is encrypted. */
076  private boolean isEncrypted;
077  /** Indicates whether to clear all base DNs in a backend. */
078  private boolean clearBackend;
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 final 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 final 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 int threadCount;
126
127  /**
128   * Creates a new LDIF import configuration that will read from the
129   * specified LDIF file.
130   *
131   * @param  ldifFile  The path to the LDIF file with the data to
132   *                   import.
133   */
134  public LDIFImportConfig(String ldifFile)
135  {
136    ldifFiles = CollectionUtils.newArrayList(ldifFile);
137    ldifFileIterator = ldifFiles.iterator();
138  }
139
140  /**
141   * Creates a new LDIF import configuration that will read from the
142   * specified LDIF files.  The files will be imported in the order
143   * they are specified in the provided list.
144   *
145   * @param  ldifFiles  The paths to the LDIF files with the data to
146   *                    import.
147   */
148  public LDIFImportConfig(List<String> ldifFiles)
149  {
150    this.ldifFiles = ldifFiles;
151    ldifFileIterator = ldifFiles.iterator();
152  }
153
154  /**
155   * Creates a new LDIF import configuration that will read from the
156   * provided input stream.
157   *
158   * @param  ldifInputStream  The input stream from which to read the
159   *                          LDIF data.
160   */
161  public LDIFImportConfig(InputStream ldifInputStream)
162  {
163    this(Collections.<String> emptyList());
164    this.ldifInputStream   = ldifInputStream;
165  }
166
167  /**
168   * Creates a new LDIF import configuration that will read from the
169   * provided reader.
170   *
171   * @param  ldifInputReader  The input stream from which to read the
172   *                          LDIF data.
173   */
174  public LDIFImportConfig(Reader ldifInputReader)
175  {
176    this(Collections.<String> emptyList());
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
439
440
441  /**
442   * Indicates whether any LDIF import plugins registered with the
443   * server should be invoked during the import operation.
444   *
445   * @return  <CODE>true</CODE> if registered LDIF import plugins
446   *          should be invoked during the import operation, or
447   *          <CODE>false</CODE> if they should not be invoked.
448   */
449  public boolean invokeImportPlugins()
450  {
451    return invokeImportPlugins;
452  }
453
454
455
456  /**
457   * Specifies whether any LDIF import plugins registered with the
458   * server should be invoked during the import operation.
459   *
460   * @param  invokeImportPlugins  Specifies whether any LDIF import
461   *                              plugins registered with the server
462   *                              should be invoked during the import
463   *                              operation.
464   */
465  public void setInvokeImportPlugins(boolean invokeImportPlugins)
466  {
467    this.invokeImportPlugins = invokeImportPlugins;
468  }
469
470
471
472  /**
473   * Indicates whether the input LDIF source is expected to be
474   * compressed.
475   *
476   * @return  <CODE>true</CODE> if the LDIF source is expected to be
477   *          compressed, or <CODE>false</CODE> if not.
478   */
479  public boolean isCompressed()
480  {
481    return isCompressed;
482  }
483
484
485
486  /**
487   * Specifies whether the input LDIF source is expected to be
488   * compressed.  If compression is used, then this must be set prior
489   * to the initial call to <CODE>getReader</CODE>.
490   *
491   * @param  isCompressed  Indicates whether the input LDIF source is
492   *                       expected to be compressed.
493   */
494  public void setCompressed(boolean isCompressed)
495  {
496    this.isCompressed = isCompressed;
497  }
498
499
500
501  /**
502   * Indicates whether the input LDIF source is expected to be
503   * encrypted.
504   *
505   * @return  <CODE>true</CODE> if the LDIF source is expected to be
506   *          encrypted, or <CODE>false</CODE> if not.
507   */
508  public boolean isEncrypted()
509  {
510    return isEncrypted;
511  }
512
513
514
515  /**
516   * Specifies whether the input LDIF source is expected to be
517   * encrypted.  If encryption is used, then this must be set prior to
518   * the initial call to <CODE>getReader</CODE>.
519   *
520   * @param  isEncrypted  Indicates whether the input LDIF source is
521   *                      expected to be encrypted.
522   */
523  public void setEncrypted(boolean isEncrypted)
524  {
525    this.isEncrypted = isEncrypted;
526  }
527
528
529
530  /**
531   * Indicates whether to clear the entire backend if importing to a
532   * backend with more than one base DNs.
533   *
534   * @return <CODE>true</code> if the entire backend should be
535   * cleared or <CODE>false</CODE> if not.
536   */
537  public boolean clearBackend()
538  {
539    return clearBackend;
540  }
541
542
543
544  /**
545   * Specifies whether to clear the entire backend if importing to a
546   * backend.
547   *
548   * @param clearBackend Indicates whether to clear the entire
549   * backend.
550   */
551  public void setClearBackend(boolean clearBackend)
552  {
553    this.clearBackend = clearBackend;
554  }
555
556
557
558  /**
559   * Indicates whether to perform schema validation on entries as they
560   * are read.
561   *
562   * @return  <CODE>true</CODE> if schema validation should be
563   *          performed on the entries as they are read, or
564   *          <CODE>false</CODE> if not.
565   */
566  public boolean validateSchema()
567  {
568    return validateSchema;
569  }
570
571
572
573  /**
574   * Specifies whether to perform schema validation on entries as they
575   * are read.
576   *
577   * @param  validateSchema  Indicates whether to perform schema
578   *                         validation on entries as they are read.
579   */
580  public void setValidateSchema(boolean validateSchema)
581  {
582    this.validateSchema = validateSchema;
583  }
584
585
586
587  /**
588   * Retrieves the set of base DNs that specify the set of entries to
589   * exclude from the import.  The contents of the returned list may
590   * be altered by the caller.
591   *
592   * @return  The set of base DNs that specify the set of entries to
593   *          exclude from the import.
594   */
595  public Set<DN> getExcludeBranches()
596  {
597    return excludeBranches;
598  }
599
600
601
602  /**
603   * Specifies the set of base DNs that specify the set of entries to
604   * exclude from the import.
605   *
606   * @param  excludeBranches  The set of base DNs that specify the set
607   *                          of entries to exclude from the import.
608   */
609  public void setExcludeBranches(Set<DN> excludeBranches)
610  {
611    this.excludeBranches = getSet(excludeBranches);
612  }
613
614  private <T> Set<T> getSet(Set<T> set)
615  {
616    return set != null ? set : new HashSet<T>(0);
617  }
618
619
620  /**
621   * Retrieves the set of base DNs that specify the set of entries to
622   * include in the import.  The contents of the returned list may be
623   * altered by the caller.
624   *
625   * @return  The set of base DNs that specify the set of entries to
626   *          include in the import.
627   */
628  public Set<DN> getIncludeBranches()
629  {
630    return includeBranches;
631  }
632
633
634
635  /**
636   * Specifies the set of base DNs that specify the set of entries to
637   * include in the import.
638   *
639   * @param  includeBranches  The set of base DNs that specify the set
640   *                          of entries to include in the import.
641   */
642  public void setIncludeBranches(Set<DN> includeBranches)
643  {
644    this.includeBranches = getSet(includeBranches);
645  }
646
647  /**
648   * Indicates whether to include the entry with the specified DN in
649   * the import.
650   *
651   * @param  dn  The DN of the entry for which to make the
652   *             determination.
653   *
654   * @return  <CODE>true</CODE> if the entry with the specified DN
655   *          should be included in the import, or <CODE>false</CODE>
656   *          if not.
657   */
658  public boolean includeEntry(DN dn)
659  {
660    if (! excludeBranches.isEmpty())
661    {
662      for (DN excludeBranch : excludeBranches)
663      {
664        if (excludeBranch.isSuperiorOrEqualTo(dn))
665        {
666          return false;
667        }
668      }
669    }
670
671    if (! includeBranches.isEmpty())
672    {
673      for (DN includeBranch : includeBranches)
674      {
675        if (includeBranch.isSuperiorOrEqualTo(dn))
676        {
677          return true;
678        }
679      }
680
681      return false;
682    }
683
684    return true;
685  }
686
687
688
689  /**
690   * Indicates whether the set of objectclasses should be included in
691   * the entries read from the LDIF.
692   *
693   * @return  <CODE>true</CODE> if the set of objectclasses should be
694   *          included in the entries read from the LDIF, or
695   *          <CODE>false</CODE> if not.
696   */
697  public boolean includeObjectClasses()
698  {
699    return includeObjectClasses;
700  }
701
702
703
704  /**
705   * Specifies whether the set of objectclasses should be included in
706   * the entries read from the LDIF.
707   *
708   * @param  includeObjectClasses  Indicates whether the set of
709   *                               objectclasses should be included in
710   *                               the entries read from the LDIF.
711   */
712  public void setIncludeObjectClasses(boolean includeObjectClasses)
713  {
714    this.includeObjectClasses = includeObjectClasses;
715  }
716
717
718
719  /**
720   * Retrieves the set of attributes that should be excluded from the
721   * entries read from the LDIF.  The contents of the returned set may
722   * be modified by the caller.
723   *
724   * @return  The set of attributes that should be excluded from the
725   *          entries read from the LDIF.
726   */
727  public Set<AttributeType> getExcludeAttributes()
728  {
729    return excludeAttributes;
730  }
731
732
733
734  /**
735   * Specifies the set of attributes that should be excluded from the
736   * entries read from the LDIF.
737   *
738   * @param  excludeAttributes  The set of attributes that should be
739   *                            excluded from the entries read from
740   *                            the LDIF.
741   */
742  public void setExcludeAttributes(Set<AttributeType> excludeAttributes)
743  {
744    this.excludeAttributes = getSet(excludeAttributes);
745  }
746
747  /**
748   * Retrieves the set of attributes that should be included in the
749   * entries read from the LDIF.  The contents of the returned set may
750   * be modified by the caller.
751   *
752   * @return  The set of attributes that should be included in the
753   *          entries read from the LDIF.
754   */
755  public Set<AttributeType> getIncludeAttributes()
756  {
757    return includeAttributes;
758  }
759
760
761
762  /**
763   * Specifies the set of attributes that should be included in the
764   * entries read from the LDIF.
765   *
766   * @param  includeAttributes  The set of attributes that should be
767   *                            included in the entries read from the
768   *                            LDIF.
769   */
770  public void setIncludeAttributes(Set<AttributeType> includeAttributes)
771  {
772    this.includeAttributes = getSet(includeAttributes);
773  }
774
775  /**
776   * Indicates whether the specified attribute should be included in
777   * the entries read from the LDIF.
778   *
779   * @param  attributeType  The attribute type for which to make the
780   *                        determination.
781   *
782   * @return  <CODE>true</CODE> if the specified attribute should be
783   *          included in the entries read from the LDIF, or
784   *         <CODE>false</CODE> if not.
785   */
786  public boolean includeAttribute(AttributeType attributeType)
787  {
788    if (!excludeAttributes.isEmpty()
789        && excludeAttributes.contains(attributeType))
790    {
791      return false;
792    }
793
794     if((excludeAllOpAttrs && attributeType.isOperational())
795         || (excludeAllUserAttrs && !attributeType.isOperational()))
796    {
797      return false;
798    }
799
800    if((includeAllUserAttrs && !attributeType.isOperational())
801        || (includeAllOpAttrs && attributeType.isOperational()))
802    {
803      return true;
804    }
805
806    if (! includeAttributes.isEmpty())
807    {
808      return includeAttributes.contains(attributeType);
809    }
810    else if((includeAllUserAttrs && attributeType.isOperational())
811        || (includeAllOpAttrs && !attributeType.isOperational()))
812    {
813      return false;
814    }
815    return true;
816  }
817
818
819
820  /**
821   * Retrieves the set of search filters that should be used to
822   * determine which entries to exclude from the LDIF.  The contents
823   * of the returned list may be modified by the caller.
824   *
825   * @return  The set of search filters that should be used to
826   *          determine which entries to exclude from the LDIF.
827   */
828  public List<SearchFilter> getExcludeFilters()
829  {
830    return excludeFilters;
831  }
832
833
834
835  /**
836   * Specifies the set of search filters that should be used to
837   * determine which entries to exclude from the LDIF.
838   *
839   * @param  excludeFilters  The set of search filters that should be
840   *                         used to determine which entries to
841   *                         exclude from the LDIF.
842   */
843  public void setExcludeFilters(List<SearchFilter> excludeFilters)
844  {
845    this.excludeFilters = getList(excludeFilters);
846  }
847
848  /**
849   * Retrieves the set of search filters that should be used to
850   * determine which entries to include in the LDIF.  The contents of
851   * the returned list may be modified by  the caller.
852   *
853   * @return  The set of search filters that should be used to
854   *          determine which entries to include in the LDIF.
855   */
856  public List<SearchFilter> getIncludeFilters()
857  {
858    return includeFilters;
859  }
860
861
862
863  /**
864   * Specifies the set of search filters that should be used to
865   * determine which entries to include in the LDIF.
866   *
867   * @param  includeFilters  The set of search filters that should be
868   *                         used to determine which entries to
869   *                         include in the LDIF.
870   */
871  public void setIncludeFilters(List<SearchFilter> includeFilters)
872  {
873    this.includeFilters = getList(includeFilters);
874  }
875
876  private <T> List<T> getList(List<T> list)
877  {
878    return list != null ? list : new ArrayList<T>(0);
879  }
880
881  /**
882   * Indicates whether the specified entry should be included in the
883   * import based on the configured set of include and exclude
884   * filters.
885   *
886   * @param  entry  The entry for which to make the determination.
887   *
888   * @return  <CODE>true</CODE> if the specified entry should be
889   *          included in the import, or <CODE>false</CODE> if not.
890   *
891   * @throws  DirectoryException  If there is a problem with any of
892   *                              the search filters used to make the
893   *                              determination.
894   */
895  public boolean includeEntry(Entry entry)
896         throws DirectoryException
897  {
898    if (! excludeFilters.isEmpty())
899    {
900      for (SearchFilter filter : excludeFilters)
901      {
902        if (filter.matchesEntry(entry))
903        {
904          return false;
905        }
906      }
907    }
908
909    if (! includeFilters.isEmpty())
910    {
911      for (SearchFilter filter : includeFilters)
912      {
913        if (filter.matchesEntry(entry))
914        {
915          return true;
916        }
917      }
918
919      return false;
920    }
921
922    return true;
923  }
924
925
926
927  /**
928   * Retrieves the buffer size that should be used when reading LDIF
929   * data.
930   *
931   * @return  The buffer size that should be used when reading LDIF
932   *          data.
933   */
934  public int getBufferSize()
935  {
936    return bufferSize;
937  }
938
939
940
941  /**
942   * Specifies the buffer size that should be used when reading LDIF
943   * data.
944   *
945   * @param  bufferSize  The buffer size that should be used when
946   *                     reading LDIF data.
947   */
948  public void setBufferSize(int bufferSize)
949  {
950    this.bufferSize = bufferSize;
951  }
952
953
954
955    /**
956   * Specifies whether all the user attributes should be excluded.
957   *
958   * @param  excludeAllUserAttrs  Specifies all user attributes to
959   *         be excluded.
960   */
961  public void setExcludeAllUserAttributes(boolean excludeAllUserAttrs)
962  {
963    this.excludeAllUserAttrs = excludeAllUserAttrs;
964  }
965
966
967
968  /**
969   * Specifies whether all the operational attributes should be
970   * excluded.
971   *
972   * @param  excludeAllOpAttrs  Specifies whether all the
973   *                            operational attributes
974   *                            should be excluded.
975   */
976  public void setExcludeAllOperationalAttributes(boolean excludeAllOpAttrs)
977  {
978    this.excludeAllOpAttrs = excludeAllOpAttrs;
979  }
980
981
982
983  /**
984   * Specifies whether all the operational attributes should be
985   * included.
986   *
987   * @param  includeAllOpAttrs  Specifies whether all
988   *         the operation attributes should be included.
989   *
990   */
991  public void setIncludeAllOpAttributes(boolean includeAllOpAttrs)
992  {
993    this.includeAllOpAttrs = includeAllOpAttrs;
994  }
995
996
997
998  /**
999   * Specifies whether all the user attributes should be included.
1000   *
1001   * @param  includeAllUserAttrs  Specifies whether all the
1002   *                              user attributes should be
1003   *                              included.
1004   */
1005  public void setIncludeAllUserAttributes(boolean includeAllUserAttrs)
1006  {
1007    this.includeAllUserAttrs = includeAllUserAttrs;
1008  }
1009
1010
1011
1012  /** Closes any resources that this import config might have open. */
1013  @Override
1014  public void close()
1015  {
1016    StaticUtils.close(reader, rejectWriter, skipWriter);
1017  }
1018
1019  /**
1020   * Set the temporary directory to the specified path.
1021   *
1022   * @param path The path to set the temporary directory to.
1023   */
1024  public void setTmpDirectory(String path)
1025  {
1026    tmpDirectory = path;
1027  }
1028
1029  /**
1030   * Return the temporary directory path.
1031   *
1032   * @return  The temporary directory string.
1033   */
1034  public String getTmpDirectory()
1035  {
1036    return tmpDirectory;
1037  }
1038
1039  /**
1040   * Set the thread count.
1041   *
1042   * @param c The thread count value.
1043   */
1044  public void setThreadCount(int c)
1045  {
1046    this.threadCount = c;
1047  }
1048
1049  /**
1050   * Return the specified thread count.
1051   *
1052   * @return The thread count.
1053   */
1054  public int getThreadCount()
1055  {
1056    return this.threadCount;
1057  }
1058}