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}