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