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}