Class RandomAccessLDIF


  • public class RandomAccessLDIF
    extends java.lang.Object
    A class which enables random-access to LDIF files for both reading and writing.
    Author:
    jp
    • Constructor Summary

      Constructors 
      Constructor Description
      RandomAccessLDIF​(java.lang.String in_fnam, java.lang.String tmp_fnam, java.lang.String out_fnam)
      Set up an RandomAccessLDIF object with the given files.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void close()
      Close the input/output files.
      java.lang.String error()
      Return the next error/warning-string stored from previous operations, or null if there are no more.
      boolean exists​(DN dn)
      Check whether the given DN exists as a real entry within the logical tree (in other words, it is a leaf or parent).
      protected void finalize()
      Releases any native structures associated with this object.
      GenericEntry get​(DN dn)
      Get the entry with the given DN from the logical contents of the object.
      boolean getAllowUnknownAttrs()
      Get the current 'allow unknown attributes' flag status.
      ChangeEntry getChange​(DN dn)
      Get the change entry with the given DN from the logical contents of the object.
      Entry getEntry​(DN dn)
      Get the normal entry with the given DN from the logical contents of the object.
      boolean isClosed()
      Check if RandomAccessLDIF has been closed yet.
      GenericEntry next()
      Get the next entry from the search as a GenericEntry.
      ChangeEntry nextChange()
      Get the next entry from the search as a ChangeEntry.
      DN nextDN()
      Get the next entry from the search as a DN.
      Entry nextEntry()
      Get the next entry from the search as an Entry.
      void put​(GenericEntry entry)
      Write an entry to the logical tree.
      boolean remove​(DN dn)
      Remove the entry with the given DN from the logical contents.
      void search​(DN dn, boolean sorted, boolean subtree)
      Start a search through the logical tree.
      void setAllowUnknownAttrs​(boolean flag)
      Set the status of the 'allow unknown attributes' flag.
      java.lang.String toString()
      Returns a String representation of the object
      boolean wasGlue()
      Test whether the last DN visited corresponds to a glue entry in the tree.
      boolean wasLeaf()
      Test whether the last DN visited corresponds to a leaf entry in the tree.
      boolean wasParent()
      Test whether the last DN visited corresponds to a parent entry in the tree.
      boolean wasReal()
      Test whether the last DN visited corresponds to a real entry in the tree (either a leaf or a parent).
      void write()
      The final output file is created and written (if one was specified in the constructor), based on the logical tree in memory and the entries from the input and cache files.
      • Methods inherited from class java.lang.Object

        clone, equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Constructor Detail

      • RandomAccessLDIF

        public RandomAccessLDIF​(java.lang.String in_fnam,
                                java.lang.String tmp_fnam,
                                java.lang.String out_fnam)
                         throws OperationFailedException,
                                java.lang.NullPointerException,
                                NativeLibraryException
        Set up an RandomAccessLDIF object with the given files. Any combination of the given files may be passed, with the remainder passed as 'null'.

        If the input filename is passed, then the logical contents of the object are initialised from this read-only LDIF file. Otherwise the logical contents of the object are initialised to an empty tree.

        If the cache filename is passed, then this allows adding new entries to the logical contents of the object. The new entries are saved temporarily in the cache file. If the caller re-reads these entries, they are re-read from the cache file as necessary. If there is a final output file, they are re-read again when that file is built up. The cache file is always deleted when the object is closed. If no cache filename is passed, then no put() calls can be made.

        If the output filename is passed, then a final output file can be written with the final logical contents of the object using the write() call. It is permissible for the input and output filenames to be the same, in which case the output file is written with ".new" appended, and on the close(), the input file is renamed with ".bak" appended and the new output file put into its place. If no output filename is passed, or if write() isn't called, then the final logical contents of the object are discarded when it is closed.

        Note that certain combinations of non-null arguments suit particular uses:

        • For read-only random-access to a file (no modifications), only the input filename is passed. Deletions are permitted to the logical contents, but they are not saved anywhere.
        • For a temporary caching file, only the cache filename is passed. The logical contents of the object are initially empty, additions and modifications are permitted to the logical contents (with new entries cached in the cache file), but everything will be discarded on close().
        • For making random-access modifications to an existing LDIF file, all three file parameters are passed, with the input and output filenames the same. The logical contents start off as a copy of the input file, tracking modifications as they are made and temporarily storing new entries in the cache file, before finally rewriting the output file from the logical contents on write() and close().

        Note that initialising the object with a large input file may take a few moments, as the file has to be scanned to create the in-memory DN tree. If there are any problems whilst scanning the input file, warnings are added to the list of strings returned by error(), and the scan continues. For this reason, it is important to check the error() function for warnings after constructing the object.

        Parameters:
        in_fnam - Input file pathname, or null for no input file
        tmp_fnam - Cache file pathname, or null for no cache file
        out_fnam - Output file pathname, or null for no output file
        Throws:
        OperationFailedException - Can't open/create one of the files
        java.lang.NullPointerException - Both arguments were null
        NativeLibraryException - Internal unrecoverable error
    • Method Detail

      • write

        public void write()
                   throws OperationFailedException,
                          NativeLibraryException
        The final output file is created and written (if one was specified in the constructor), based on the logical tree in memory and the entries from the input and cache files. Note that if the input and output filenames are the same, then this only writes the .new file; it doesn't rename the files (which is done in the final close()). This means that it is possible to repeat this call if it fails.

        There may be problems whilst writing the output file, which cause the function to return with OperationFailedException; any partial output file is deleted in this case.

        Throws:
        OperationFailedException - Writing the output file failed; see the error() output
        NativeLibraryException - Internal unrecoverable error
      • close

        public void close()
                   throws OperationFailedException,
                          NativeLibraryException
        Close the input/output files. The cache file is deleted, and the input and output files are renamed (if the output file is overwriting the input file). Note that if an output file is required, then write() must be called before close().

        If deleting or renaming files fails, then the files may be left in an inconsistant state: the cache file may still be there, and the new copy of the output file may still have its .new extension instead of having been renamed in place of the original file. These errors are logged, and OperationFailedException will be thrown in this case.

        If any operation is attempted on the object after this call, a NativeLibraryException will be thrown. In particular, fetching errors with error() must be done before closing the stream.

        Note that a close() is done automatically when the object is finalized by Java, but the delay before this happens is unpredictable. For this reason it is vital to close the files manually with this call.

        Throws:
        NativeLibraryException - Internal unrecoverable error
        OperationFailedException - Final delete of cache file or renames of input files didn't complete successfully.
      • setAllowUnknownAttrs

        public void setAllowUnknownAttrs​(boolean flag)
        Set the status of the 'allow unknown attributes' flag. With this flag set, unknown attributes found in the LDIF file won't be rejected with an error, but will be passed back with an 'octetstring' syntax. These unknown attributes can be written over LDAP or to LDIF files, but not sent over DAP.
        Parameters:
        flag - Allow unknown attributes?
      • getAllowUnknownAttrs

        public boolean getAllowUnknownAttrs()
        Get the current 'allow unknown attributes' flag status.
        Returns:
        Allow unknown attributes?
      • put

        public void put​(GenericEntry entry)
                 throws OperationFailedException,
                        java.lang.NullPointerException,
                        BadEntryException,
                        BadDNException,
                        NativeLibraryException
        Write an entry to the logical tree. This overwrites any existing entry with the same DN. This operation is permitted only if there is a cache file active. Any GenericEntry subclass instance may be written -- Entry, AddEntry, ModifyEntry, DeleteEntry or RenameEntry -- although normal entries and change-entries cannot be mixed in the same file.
        Parameters:
        entry - GenericEntry to write
        Throws:
        OperationFailedException - Error writing data to the file
        java.lang.NullPointerException - Argument is null
        BadEntryException - The entry could not be converted to LDIF format
        BadDNException - The DN could not be converted to LDIF format
        NativeLibraryException - Internal unrecoverable error
      • wasLeaf

        public boolean wasLeaf()
                        throws NativeLibraryException
        Test whether the last DN visited corresponds to a leaf entry in the tree. This tests the last entry visited by exists(), get(), getEntry(), getChange(), nextDN(), next(), nextEntry() or nextChange(). The type of the last-visited logical tree entry may be: leaf entry, parent entry, glue entry or missing.
        Returns:
        'true' if last DN visited was a leaf
        Throws:
        NativeLibraryException - Internal unrecoverable error
      • wasParent

        public boolean wasParent()
                          throws NativeLibraryException
        Test whether the last DN visited corresponds to a parent entry in the tree. This tests the last entry visited by exists(), get(), getEntry(), getChange(), nextDN(), next(), nextEntry() or nextChange(). The type of the last-visited logical tree entry may be: leaf entry, parent entry, glue entry or missing.
        Returns:
        'true' if last DN visited was a parent
        Throws:
        NativeLibraryException - Internal unrecoverable error
      • wasReal

        public boolean wasReal()
                        throws NativeLibraryException
        Test whether the last DN visited corresponds to a real entry in the tree (either a leaf or a parent). This tests the last entry visited by exists(), get(), getEntry(), getChange(), nextDN(), next(), nextEntry() or nextChange(). The type of the last-visited logical tree entry may be: leaf entry, parent entry, glue entry or missing.
        Returns:
        'true' if last DN visited was a parent or leaf
        Throws:
        NativeLibraryException - Internal unrecoverable error
      • wasGlue

        public boolean wasGlue()
                        throws NativeLibraryException
        Test whether the last DN visited corresponds to a glue entry in the tree. This tests the last entry visited by exists(), get(), getEntry(), getChange(), nextDN(), next(), nextEntry() or nextChange(). The type of the last-visited logical tree entry may be: leaf entry, parent entry, glue entry or missing.
        Returns:
        'true' if last DN visited was a glue entry
        Throws:
        NativeLibraryException - Internal unrecoverable error
      • exists

        public boolean exists​(DN dn)
                       throws NativeLibraryException
        Check whether the given DN exists as a real entry within the logical tree (in other words, it is a leaf or parent). Real entries must have entry-data associated with them, so glue entries do not count.
        Returns:
        DN corresponds to a real entry?
        Throws:
        NativeLibraryException - Internal unrecoverable error
      • remove

        public boolean remove​(DN dn)
                       throws NativeLibraryException
        Remove the entry with the given DN from the logical contents.
        Returns:
        true: deleted, false: not found
        Throws:
        NativeLibraryException - Internal unrecoverable error
      • error

        public java.lang.String error()
                               throws NativeLibraryException
        Return the next error/warning-string stored from previous operations, or null if there are no more. Note that one error/warning string is returned per call, so this call must be repeated until all errors have been exhausted.
        Returns:
        Error/warning string, or null
        Throws:
        NativeLibraryException - Internal unrecoverable error
      • search

        public void search​(DN dn,
                           boolean sorted,
                           boolean subtree)
                    throws OperationFailedException,
                           NativeLibraryException
        Start a search through the logical tree. The starting point of the scan is below the given DN, or starting from root if 'dn' is null. The data is returned sorted if 'sorted' is true, otherwise in the internal ordering (which may be a hashed ordering). The scan is a one-level scan, unless 'subtree' is true, in which case it is a subtree scan with each subtree dumped immediately after its parent. There can be only one search active at any one time in any given RandomAccessLDIF instance.

        Note that adding or deleting entries in the logical tree causes the search to be aborted. Any next() or nextDN() call made after changes to the logical tree will throw an exception.

        Parameters:
        dn - DN to search below, or null to start from root
        sorted - Sorted search? Otherwise unsorted.
        subtree - Subtree search? Otherwise a one-level search.
        Throws:
        OperationFailedException - There was no entry with that DN
        NativeLibraryException - Internal unrecoverable error
      • isClosed

        public boolean isClosed()
        Check if RandomAccessLDIF has been closed yet.
        Returns:
        'true' if it has been closed
      • finalize

        protected void finalize()
                         throws java.lang.Throwable
        Releases any native structures associated with this object.
        Overrides:
        finalize in class java.lang.Object
        Throws:
        java.lang.Throwable
      • toString

        public java.lang.String toString()
        Returns a String representation of the object
        Overrides:
        toString in class java.lang.Object
        Returns:
        String representation of the object