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.replication.plugin;
028    
029    
030    import java.io.IOException;
031    import java.io.OutputStream;
032    
033    import org.opends.server.util.ServerConstants;
034    
035    /**
036     * This class creates an output stream that can be used to export entries
037     * to a synchonization domain.
038     */
039    public class ReplLDIFOutputStream
040           extends OutputStream
041    {
042      // The synchronization domain on which the export is done
043      ReplicationDomain domain;
044    
045      // The number of entries to be exported
046      long numEntries;
047    
048      // The current number of entries exported
049      private long numExportedEntries;
050      String entryBuffer = "";
051    
052      /**
053       * Creates a new ReplLDIFOutputStream related to a replication
054       * domain.
055       *
056       * @param domain The replication domain
057       * @param numEntries The max number of entry to process.
058       */
059      public ReplLDIFOutputStream(ReplicationDomain domain, long numEntries)
060      {
061        this.domain = domain;
062        this.numEntries = numEntries;
063      }
064    
065      /**
066       * {@inheritDoc}
067       */
068      public void write(int i) throws IOException
069      {
070        throw new IOException("Invalid call");
071      }
072    
073      /**
074       * {@inheritDoc}
075       */
076      public void write(byte b[], int off, int len) throws IOException
077      {
078        int endOfEntryIndex;
079        int endIndex;
080    
081        String ebytes = "";
082        ebytes = ebytes.concat(entryBuffer);
083        entryBuffer = "";
084    
085        ebytes = ebytes.concat(new String(b, off, len));
086        endIndex = ebytes.length();
087    
088        while (true)
089        {
090          // if we have the bytes for an entry, let's make an entry and send it
091          endOfEntryIndex = ebytes.indexOf(ServerConstants.EOL +
092              ServerConstants.EOL);
093    
094          if ( endOfEntryIndex >= 0 )
095          {
096            endOfEntryIndex += 2;
097            entryBuffer = ebytes.substring(0, endOfEntryIndex);
098    
099            // Send the entry
100            if ((numEntries>0) && (getNumExportedEntries() > numEntries))
101            {
102              // This outputstream has reached the total number
103              // of entries to export.
104              throw(new IOException());
105            }
106            domain.exportLDIFEntry(entryBuffer);
107            numExportedEntries++;
108            entryBuffer = "";
109    
110            if (endIndex == endOfEntryIndex)
111            {
112              // no more data to process
113              break;
114            }
115            else
116            {
117              // loop to the data of the next entry
118              ebytes = ebytes.substring(endOfEntryIndex,
119                                        endIndex);
120              endIndex = ebytes.length();
121            }
122          }
123          else
124          {
125            // a next call to us will provide more bytes to make an entry
126            entryBuffer = entryBuffer.concat(ebytes);
127            break;
128          }
129        }
130      }
131    
132      /**
133       * Return the number of exported entries.
134       * @return the numExportedEntries
135       */
136      public long getNumExportedEntries() {
137        return numExportedEntries;
138      }
139    }