001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2015 ForgeRock AS.
026 */
027package org.opends.server.replication.plugin;
028
029
030import java.io.IOException;
031import java.io.OutputStream;
032
033import org.opends.server.util.ServerConstants;
034
035/**
036 * This class creates an output stream that can be used to export entries
037 * to a synchronization domain.
038 */
039public class ReplLDIFOutputStream
040       extends OutputStream
041{
042  /** The number of entries to be exported. */
043  long numEntries;
044
045  /** The current number of entries exported. */
046  private long numExportedEntries;
047  String entryBuffer = "";
048
049  /** The checksum for computing the generation id. */
050  private GenerationIdChecksum checkSum = new GenerationIdChecksum();
051
052  /**
053   * Creates a new ReplLDIFOutputStream related to a replication
054   * domain.
055   *
056   * @param numEntries The max number of entry to process.
057   */
058  public ReplLDIFOutputStream(long numEntries)
059  {
060    this.numEntries = numEntries;
061  }
062
063  /** {@inheritDoc} */
064  public void write(int i) throws IOException
065  {
066    throw new IOException("Invalid call");
067  }
068
069  /**
070   * Get the value of the underlying checksum.
071   * @return The value of the underlying checksum
072   */
073  public long getChecksumValue()
074  {
075    return checkSum.getValue();
076  }
077
078  /** {@inheritDoc} */
079  public void write(byte b[], int off, int len) throws IOException
080  {
081    int endOfEntryIndex;
082    int endIndex;
083
084    String ebytes = "";
085    ebytes = ebytes.concat(entryBuffer);
086    entryBuffer = "";
087
088    ebytes = ebytes.concat(new String(b, off, len));
089    endIndex = ebytes.length();
090
091    while (true)
092    {
093      // if we have the bytes for an entry, let's make an entry and send it
094      endOfEntryIndex = ebytes.indexOf(ServerConstants.EOL +
095          ServerConstants.EOL);
096
097      if ( endOfEntryIndex >= 0 )
098      {
099        endOfEntryIndex += 2;
100        entryBuffer = ebytes.substring(0, endOfEntryIndex);
101
102        // Send the entry
103        if (numEntries>0 && getNumExportedEntries() > numEntries)
104        {
105          // This outputstream has reached the total number
106          // of entries to export.
107          throw new IOException();
108        }
109
110        // Add the entry bytes to the checksum
111        byte[] entryBytes = entryBuffer.getBytes();
112        checkSum.update(entryBytes, 0, entryBytes.length);
113
114        numExportedEntries++;
115        entryBuffer = "";
116
117        if (endIndex == endOfEntryIndex)
118        {
119          // no more data to process
120          break;
121        }
122        else
123        {
124          // loop to the data of the next entry
125          ebytes = ebytes.substring(endOfEntryIndex,
126                                    endIndex);
127          endIndex = ebytes.length();
128        }
129      }
130      else
131      {
132        // a next call to us will provide more bytes to make an entry
133        entryBuffer = entryBuffer.concat(ebytes);
134        break;
135      }
136    }
137  }
138
139  /**
140   * Return the number of exported entries.
141   * @return the numExportedEntries
142   */
143  public long getNumExportedEntries() {
144    return numExportedEntries;
145  }
146}