| | |
| | | package org.opends.server.synchronization; |
| | | |
| | | import java.io.Serializable; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.util.zip.DataFormatException; |
| | | |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.ModifyDNOperation; |
| | | import org.opends.server.core.ModifyOperation; |
| | | import org.opends.server.core.Operation; |
| | | import org.opends.server.protocols.asn1.ASN1Exception; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | |
| | | /** |
| | | * The ChangeNumber of this update. |
| | | */ |
| | | protected ChangeNumber changeNumber; |
| | | private ChangeNumber changeNumber; |
| | | |
| | | /** |
| | | * The DN on which the update was originally done. |
| | | */ |
| | | private String dn = null; |
| | | |
| | | /** |
| | | * True when the update must use assured replication. |
| | |
| | | private boolean assuredFlag = false; |
| | | |
| | | /** |
| | | * The UniqueId of the entry that was updated. |
| | | */ |
| | | private String UniqueId; |
| | | |
| | | /** |
| | | * Creates a new UpdateMessage with the given informations. |
| | | * |
| | | * @param ctx The Synchronization Context of the operation for which the |
| | | * update message must be created,. |
| | | * @param dn The dn of the entry on which the change |
| | | * that caused the creation of this object happened |
| | | */ |
| | | public UpdateMessage(OperationContext ctx, String dn) |
| | | { |
| | | this.changeNumber = ctx.getChangeNumber(); |
| | | this.UniqueId = ctx.getEntryUid(); |
| | | this.dn = dn; |
| | | } |
| | | |
| | | /** |
| | | * Creates a new UpdateMessage from an ecoded byte array. |
| | | * |
| | | * @param in The encoded byte array containind the UpdateMessage. |
| | | * @throws DataFormatException if the encoded byte array is not valid. |
| | | * @throws UnsupportedEncodingException if UTF-8 is not supprted. |
| | | */ |
| | | public UpdateMessage(byte[] in) throws DataFormatException, |
| | | UnsupportedEncodingException |
| | | { |
| | | /* read the changeNumber */ |
| | | int pos = 1; |
| | | int length = getNextLength(in, pos); |
| | | String changenumberStr = new String(in, pos, length, "UTF-8"); |
| | | this.changeNumber = new ChangeNumber(changenumberStr); |
| | | } |
| | | |
| | | /** |
| | | * Generates an Update Message which the provided information. |
| | | * |
| | | * @param op The operation fo which the message must be created. |
| | | * @param isAssured flag indicating if the operation is an assured operation. |
| | | * @return The generated message. |
| | | */ |
| | | public static UpdateMessage generateMsg(Operation op, boolean isAssured) |
| | | { |
| | | UpdateMessage msg = null; |
| | | switch (op.getOperationType()) |
| | | { |
| | | case MODIFY : |
| | | msg = new ModifyMsg((ModifyOperation) op); |
| | | if (isAssured) |
| | | msg.setAssured(); |
| | | break; |
| | | |
| | | case ADD: |
| | | msg = new AddMsg((AddOperation) op); |
| | | if (isAssured) |
| | | msg.setAssured(); |
| | | break; |
| | | |
| | | case DELETE : |
| | | msg = new DeleteMsg((DeleteOperation) op); |
| | | if (isAssured) |
| | | msg.setAssured(); |
| | | break; |
| | | |
| | | case MODIFY_DN : |
| | | msg = new ModifyDNMsg((ModifyDNOperation) op); |
| | | if (isAssured) |
| | | msg.setAssured(); |
| | | break; |
| | | } |
| | | |
| | | return msg; |
| | | } |
| | | |
| | | /** |
| | | * Get the ChangeNumber from the message. |
| | | * @return the ChangeNumber |
| | | */ |
| | |
| | | } |
| | | |
| | | /** |
| | | * Get the DN on which the operation happened. |
| | | * |
| | | * @return The DN on which the operations happened. |
| | | */ |
| | | public String getDn() |
| | | { |
| | | return dn; |
| | | } |
| | | |
| | | /** |
| | | * Set the DN. |
| | | * @param dn The dn that must now be used for this message. |
| | | */ |
| | | public void setDn(String dn) |
| | | { |
| | | this.dn = dn; |
| | | } |
| | | |
| | | /** |
| | | * Get the Unique Identifier of the entry on which the operation happened. |
| | | * |
| | | * @return The Unique Identifier of the entry on which the operation happened. |
| | | */ |
| | | public String getUniqueId() |
| | | { |
| | | return UniqueId; |
| | | } |
| | | |
| | | /** |
| | | * Get a boolean indicating if the Update must be processed as an |
| | | * Asynchronous or as an assured synchronization. |
| | | * |
| | |
| | | * @throws ASN1Exception In case of ASN1 decoding exception. |
| | | * @throws DataFormatException In case of bad msg format. |
| | | */ |
| | | public abstract Operation createOperation(InternalClientConnection conn) |
| | | public Operation createOperation(InternalClientConnection conn) |
| | | throws LDAPException, ASN1Exception, DataFormatException |
| | | { |
| | | return createOperation(conn, dn); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create and Operation from the message using the provided DN. |
| | | * |
| | | * @param conn connection to use when creating the message. |
| | | * @param newDn the DN to use when creating the operation. |
| | | * @return the created Operation. |
| | | * @throws LDAPException In case of LDAP decoding exception. |
| | | * @throws ASN1Exception In case of ASN1 decoding exception. |
| | | * @throws DataFormatException In case of bad msg format. |
| | | */ |
| | | public abstract Operation createOperation(InternalClientConnection conn, |
| | | String newDn) |
| | | throws LDAPException, ASN1Exception, DataFormatException; |
| | | |
| | | /** |
| | | * Encode the common header for all the UpdateMessage. |
| | | * |
| | | * @param type the type of UpdateMessage to encode. |
| | | * @param additionalLength additional length needed to encode the remaining |
| | | * part of the UpdateMessage. |
| | | * @return a byte array containing the common header and enough space to |
| | | * encode the reamining bytes of the UpdateMessage as was specified |
| | | * by the additionalLength. |
| | | * (byte array length = common header length + additionalLength) |
| | | * @throws UnsupportedEncodingException if UTF-8 is not supported. |
| | | */ |
| | | public byte[] encodeHeader(byte type, int additionalLength) |
| | | throws UnsupportedEncodingException |
| | | { |
| | | byte[] byteDn = dn.getBytes("UTF-8"); |
| | | byte[] changeNumberByte = |
| | | this.getChangeNumber().toString().getBytes("UTF-8"); |
| | | byte[] byteEntryuuid = getUniqueId().getBytes("UTF-8"); |
| | | |
| | | /* The message header is stored in the form : |
| | | * <operation type>changenumber><dn><entryuuid><change> |
| | | * the length of result byte array is therefore : |
| | | * 1 + dn length + 1 + 24 + additional_length |
| | | */ |
| | | int length = 1 + changeNumberByte.length + 1 + byteDn.length + 1 |
| | | + byteEntryuuid.length + 1 + additionalLength; |
| | | |
| | | byte[] encodedMsg = new byte[length]; |
| | | |
| | | /* put the type of the operation */ |
| | | encodedMsg[0] = type; |
| | | int pos = 1; |
| | | |
| | | /* put the ChangeNumber */ |
| | | pos = addByteArray(changeNumberByte, encodedMsg, pos); |
| | | |
| | | /* put the DN and a terminating 0 */ |
| | | pos = addByteArray(byteDn, encodedMsg, pos); |
| | | |
| | | /* put the entry uuid and a terminating 0 */ |
| | | pos = addByteArray(byteEntryuuid, encodedMsg, pos); |
| | | |
| | | return encodedMsg; |
| | | } |
| | | |
| | | /** |
| | | * Decode the Header part of this Update Message, and check its type. |
| | | * |
| | | * @param type The type of this Update Message. |
| | | * @param encodedMsg the encoded form of the UpdateMessage. |
| | | * @return the position at which the remaining part of the message starts. |
| | | * @throws DataFormatException if the encodedMsg does not contain a valid |
| | | * common header. |
| | | */ |
| | | public int decodeHeader(byte type, byte [] encodedMsg) |
| | | throws DataFormatException |
| | | { |
| | | /* first byte is the type */ |
| | | if (encodedMsg[0] != type) |
| | | throw new DataFormatException("byte[] is not a valid msg"); |
| | | |
| | | try |
| | | { |
| | | /* read the changeNumber */ |
| | | int pos = 1; |
| | | int length = getNextLength(encodedMsg, pos); |
| | | String changenumberStr = new String(encodedMsg, pos, length, "UTF-8"); |
| | | pos += length + 1; |
| | | changeNumber = new ChangeNumber(changenumberStr); |
| | | |
| | | /* read the dn */ |
| | | length = getNextLength(encodedMsg, pos); |
| | | dn = new String(encodedMsg, pos, length, "UTF-8"); |
| | | pos += length + 1; |
| | | |
| | | /* read the entryuuid */ |
| | | length = getNextLength(encodedMsg, pos); |
| | | UniqueId = new String(encodedMsg, pos, length, "UTF-8"); |
| | | pos += length + 1; |
| | | |
| | | return pos; |
| | | } catch (UnsupportedEncodingException e) |
| | | { |
| | | throw new DataFormatException("UTF-8 is not supported by this jvm."); |
| | | } |
| | | |
| | | } |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |