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.protocol; 028 029 import java.io.UnsupportedEncodingException; 030 import java.util.zip.DataFormatException; 031 032 033 /** 034 * This abstract message class is the superclass for start messages used 035 * by LDAP servers and Replication servers to initiate their communications. 036 * This class specifies a message header that contains the Replication 037 * Protocol version. 038 */ 039 public abstract class StartMessage extends ReplicationMessage 040 { 041 private short protocolVersion; 042 private long generationId; 043 044 /** 045 * The length of the header of this message. 046 */ 047 protected int headerLength; 048 049 /** 050 * Create a new StartMessage. 051 * 052 * @param protocolVersion The Replication Protocol version of the server 053 * for which the StartMessage is created. 054 * @param generationId The generationId for this server. 055 * 056 */ 057 public StartMessage(short protocolVersion, long generationId) 058 { 059 this.protocolVersion = protocolVersion; 060 this.generationId = generationId; 061 } 062 063 /** 064 * Creates a new ServerStartMessage from its encoded form. 065 * 066 * @param type The type of the message to create. 067 * @param encodedMsg The byte array containing the encoded form of the 068 * StartMessage. 069 * @throws DataFormatException If the byte array does not contain a valid 070 * encoded form of the ServerStartMessage. 071 */ 072 public StartMessage(byte type, byte [] encodedMsg) throws DataFormatException 073 { 074 headerLength = decodeHeader(type, encodedMsg); 075 } 076 077 /** 078 * Encode the header for the start message. 079 * 080 * @param type The type of the message to create. 081 * @param additionalLength additional length needed to encode the remaining 082 * part of the UpdateMessage. 083 * @return a byte array containing the common header and enough space to 084 * encode the reamining bytes of the UpdateMessage as was specified 085 * by the additionalLength. 086 * (byte array length = common header length + additionalLength) 087 * @throws UnsupportedEncodingException if UTF-8 is not supported. 088 */ 089 public byte[] encodeHeader(byte type, int additionalLength) 090 throws UnsupportedEncodingException 091 { 092 byte[] versionByte = Short.toString(protocolVersion).getBytes("UTF-8"); 093 byte[] byteGenerationID = 094 String.valueOf(generationId).getBytes("UTF-8"); 095 096 /* The message header is stored in the form : 097 * <message type><protocol version> 098 */ 099 int length = 1 + versionByte.length + 1 + 100 byteGenerationID.length + 1 + 101 additionalLength; 102 103 byte[] encodedMsg = new byte[length]; 104 105 /* put the type of the operation */ 106 encodedMsg[0] = type; 107 int pos = 1; 108 109 /* put the protocol version */ 110 pos = addByteArray(versionByte, encodedMsg, pos); 111 112 /* put the generationId */ 113 headerLength = addByteArray(byteGenerationID, encodedMsg, pos); 114 115 return encodedMsg; 116 } 117 118 /** 119 * Decode the Header part of this message, and check its type. 120 * 121 * @param type The type of this message. 122 * @param encodedMsg the encoded form of the message. 123 * @return the position at which the remaining part of the message starts. 124 * @throws DataFormatException if the encodedMsg does not contain a valid 125 * common header. 126 */ 127 public int decodeHeader(byte type, byte [] encodedMsg) 128 throws DataFormatException 129 { 130 /* first byte is the type */ 131 if (encodedMsg[0] != type) 132 throw new DataFormatException("byte[] is not a valid msg"); 133 134 try 135 { 136 /* then read the version */ 137 int pos = 1; 138 int length = getNextLength(encodedMsg, pos); 139 protocolVersion = Short.valueOf( 140 new String(encodedMsg, pos, length, "UTF-8")); 141 pos += length + 1; 142 143 /* read the generationId */ 144 length = getNextLength(encodedMsg, pos); 145 generationId = Long.valueOf(new String(encodedMsg, pos, length, 146 "UTF-8")); 147 pos += length +1; 148 149 150 return pos; 151 } catch (UnsupportedEncodingException e) 152 { 153 throw new DataFormatException("UTF-8 is not supported by this jvm."); 154 } 155 156 } 157 158 /** 159 * Get the version included in the Start Message mean the replication 160 * protocol version used by the server that created the message. 161 * 162 * @return The version used by the server that created the message. 163 */ 164 public short getVersion() 165 { 166 return protocolVersion; 167 } 168 169 /** 170 * Get the generationId from this message. 171 * @return The generationId. 172 */ 173 public long getGenerationId() 174 { 175 return generationId; 176 } 177 178 }