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 static org.opends.server.replication.protocol.OperationContext.*; 030 031 import java.io.UnsupportedEncodingException; 032 import java.util.zip.DataFormatException; 033 034 import org.opends.server.core.ModifyDNOperationBasis; 035 import org.opends.server.protocols.asn1.ASN1OctetString; 036 import org.opends.server.protocols.internal.InternalClientConnection; 037 import org.opends.server.replication.common.ChangeNumber; 038 import org.opends.server.types.AbstractOperation; 039 import org.opends.server.types.DN; 040 import org.opends.server.types.DirectoryException; 041 import org.opends.server.types.RDN; 042 import org.opends.server.types.operation.PostOperationModifyDNOperation; 043 044 /** 045 * Message used to send Modify DN information. 046 */ 047 public class ModifyDNMsg extends UpdateMessage 048 { 049 private String newRDN; 050 private String newSuperior; 051 private boolean deleteOldRdn; 052 private String newSuperiorId; 053 private static final long serialVersionUID = -4905520652801395185L; 054 055 /** 056 * construct a new Modify DN message. 057 * 058 * @param operation The operation to use for building the message 059 */ 060 public ModifyDNMsg(PostOperationModifyDNOperation operation) 061 { 062 super((OperationContext) operation.getAttachment(SYNCHROCONTEXT), 063 operation.getRawEntryDN().stringValue()); 064 065 ModifyDnContext ctx = 066 (ModifyDnContext) operation.getAttachment(SYNCHROCONTEXT); 067 newSuperiorId = ctx.getNewParentId(); 068 069 deleteOldRdn = operation.deleteOldRDN(); 070 if (operation.getRawNewSuperior() != null) 071 newSuperior = operation.getRawNewSuperior().stringValue(); 072 else 073 newSuperior = null; 074 newRDN = operation.getRawNewRDN().stringValue(); 075 } 076 077 /** 078 * construct a new Modify DN message. 079 * 080 * @param dn The dn to use for building the message. 081 * @param changeNumber The changeNumberto use for building the message. 082 * @param uid The unique id to use for building the message. 083 * @param newParentUid The new parent unique id to use for building 084 * the message. 085 * @param deleteOldRdn boolean indicating if old rdn must be deleted to use 086 * for building the message. 087 * @param newSuperior The new Superior entry to use for building the message. 088 * @param newRDN The new Rdn to use for building the message. 089 */ 090 public ModifyDNMsg(String dn, ChangeNumber changeNumber, String uid, 091 String newParentUid, boolean deleteOldRdn, 092 String newSuperior, String newRDN) 093 { 094 super(new ModifyDnContext(changeNumber, uid, newParentUid), dn); 095 096 newSuperiorId = newParentUid; 097 098 this.deleteOldRdn = deleteOldRdn; 099 this.newSuperior = newSuperior; 100 this.newRDN = newRDN; 101 } 102 103 /** 104 * Creates a new ModifyDN message from a byte[]. 105 * 106 * @param in The byte[] from which the operation must be read. 107 * @throws DataFormatException The input byte[] is not a valid AddMsg. 108 * @throws UnsupportedEncodingException If UTF8 is not supported. 109 */ 110 public ModifyDNMsg(byte[] in) throws DataFormatException, 111 UnsupportedEncodingException 112 { 113 super(in); 114 115 int pos = decodeHeader(MSG_TYPE_MODIFYDN_REQUEST, in); 116 117 /* read the newRDN 118 * first calculate the length then construct the string 119 */ 120 int length = getNextLength(in, pos); 121 newRDN = new String(in, pos, length, "UTF-8"); 122 pos += length + 1; 123 124 /* read the newSuperior 125 * first calculate the length then construct the string 126 */ 127 length = getNextLength(in, pos); 128 if (length != 0) 129 newSuperior = new String(in, pos, length, "UTF-8"); 130 else 131 newSuperior = null; 132 pos += length + 1; 133 134 /* read the new parent Id 135 */ 136 length = getNextLength(in, pos); 137 if (length != 0) 138 newSuperiorId = new String(in, pos, length, "UTF-8"); 139 else 140 newSuperiorId = null; 141 pos += length + 1; 142 143 /* get the deleteoldrdn flag */ 144 if (in[pos] == 0) 145 deleteOldRdn = false; 146 else 147 deleteOldRdn = true; 148 } 149 150 /** 151 * {@inheritDoc} 152 */ 153 @Override 154 public AbstractOperation createOperation( 155 InternalClientConnection connection, String newDn) 156 { 157 ModifyDNOperationBasis moddn = new ModifyDNOperationBasis(connection, 158 InternalClientConnection.nextOperationID(), 159 InternalClientConnection.nextMessageID(), null, 160 new ASN1OctetString(newDn), new ASN1OctetString(newRDN), 161 deleteOldRdn, 162 (newSuperior == null ? null : new ASN1OctetString(newSuperior))); 163 ModifyDnContext ctx = new ModifyDnContext(getChangeNumber(), getUniqueId(), 164 newSuperiorId); 165 moddn.setAttachment(SYNCHROCONTEXT, ctx); 166 return moddn; 167 } 168 169 /** 170 * Get the byte array representation of this Message. 171 * 172 * @return The byte array representation of this Message. 173 * 174 * @throws UnsupportedEncodingException When the encoding of the message 175 * failed because the UTF-8 encoding is not supported. 176 */ 177 @Override 178 public byte[] getBytes() throws UnsupportedEncodingException 179 { 180 byte[] byteNewRdn = newRDN.getBytes("UTF-8"); 181 byte[] byteNewSuperior = null; 182 byte[] byteNewSuperiorId = null; 183 184 // calculate the length necessary to encode the parameters 185 int length = byteNewRdn.length + 1 + 1; 186 if (newSuperior != null) 187 { 188 byteNewSuperior = newSuperior.getBytes("UTF-8"); 189 length += byteNewSuperior.length + 1; 190 } 191 else 192 length += 1; 193 194 if (newSuperiorId != null) 195 { 196 byteNewSuperiorId = newSuperiorId.getBytes("UTF-8"); 197 length += byteNewSuperiorId.length + 1; 198 } 199 else 200 length += 1; 201 202 byte[] resultByteArray = encodeHeader(MSG_TYPE_MODIFYDN_REQUEST, length); 203 int pos = resultByteArray.length - length; 204 205 /* put the new RDN and a terminating 0 */ 206 pos = addByteArray(byteNewRdn, resultByteArray, pos); 207 208 /* put the newsuperior and a terminating 0 */ 209 if (newSuperior != null) 210 { 211 pos = addByteArray(byteNewSuperior, resultByteArray, pos); 212 } 213 else 214 resultByteArray[pos++] = 0; 215 216 /* put the newsuperiorId and a terminating 0 */ 217 if (newSuperiorId != null) 218 { 219 pos = addByteArray(byteNewSuperiorId, resultByteArray, pos); 220 } 221 else 222 resultByteArray[pos++] = 0; 223 224 /* put the deleteoldrdn flag */ 225 if (deleteOldRdn) 226 resultByteArray[pos++] = 1; 227 else 228 resultByteArray[pos++] = 0; 229 230 return resultByteArray; 231 } 232 233 /** 234 * {@inheritDoc} 235 */ 236 @Override 237 public String toString() 238 { 239 return ("MODDN " + getDn() + " " + newRDN + " " + newSuperior + " " + 240 getChangeNumber()); 241 } 242 243 /** 244 * Set the new superior. 245 * @param string the new superior. 246 */ 247 public void setNewSuperior(String string) 248 { 249 newSuperior = string; 250 } 251 252 /** 253 * Get the new RDN of this operation. 254 * 255 * @return The new RDN of this operation. 256 */ 257 public String getNewRDN() 258 { 259 return newRDN; 260 } 261 262 /** 263 * Set the new RDN of this operation. 264 * @param newRDN the new RDN of this operation. 265 */ 266 public void setNewRDN(String newRDN) 267 { 268 this.newRDN = newRDN; 269 } 270 271 /** 272 * Check if this MSG will change the DN of the target entry to be 273 * the same as the dn given as a parameter. 274 * @param targetDn the DN to use when checking if this MSG will change 275 * the DN of the entry to a given DN. 276 * @return A boolean indicating if the modify DN MSG will change the DN of 277 * the target entry to be the same as the dn given as a parameter. 278 */ 279 public boolean newDNIsParent(DN targetDn) 280 { 281 try 282 { 283 DN newDN; 284 if (newSuperior == null) 285 { 286 DN parentDn = DN.decode(this.getDn()).getParent(); 287 newDN = parentDn.concat(RDN.decode(newRDN)); 288 } 289 else 290 { 291 String newStringDN = newRDN + "," + newSuperior; 292 newDN = DN.decode(newStringDN); 293 } 294 295 296 if (newDN.isAncestorOf(targetDn)) 297 return true; 298 else 299 return false; 300 } catch (DirectoryException e) 301 { 302 // The DN was not a correct DN, and therefore does not a parent of the 303 // DN given as a parameter. 304 return false; 305 } 306 } 307 308 /** 309 * Check if the new dn of this ModifyDNMsg is the same as the targetDN 310 * given in parameter. 311 * 312 * @param targetDN The targetDN to use to check for equality. 313 * 314 * @return A boolean indicating if the targetDN if the same as the new DN of 315 * the ModifyDNMsg. 316 */ 317 public boolean newDNIsEqual(DN targetDN) 318 { 319 try 320 { 321 String newStringDN = newRDN + "," + newSuperior; 322 DN newDN = DN.decode(newStringDN); 323 324 if (newDN.equals(targetDN)) 325 return true; 326 else 327 return false; 328 } catch (DirectoryException e) 329 { 330 // The DN was not a correct DN, and therefore does not match the 331 // DN given as a parameter. 332 return false; 333 } 334 } 335 336 /** 337 * Check if the new parent of the modifyDNMsg is the same as the targetDN 338 * given in parameter. 339 * 340 * @param targetDN the targetDN to use when checking equality. 341 * 342 * @return A boolean indicating if the new parent of the modifyDNMsg is the 343 * same as the targetDN. 344 */ 345 public boolean newParentIsEqual(DN targetDN) 346 { 347 try 348 { 349 DN newSuperiorDN = DN.decode(newSuperior); 350 351 if (newSuperiorDN.equals(targetDN)) 352 return true; 353 else 354 return false; 355 } catch (DirectoryException e) 356 { 357 // The newsuperior was not a correct DN, and therefore does not match the 358 // DN given as a parameter. 359 return false; 360 } 361 } 362 363 }