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