001/* 002 * Copyright 2009-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.protocol; 037 038 039 040import com.unboundid.asn1.ASN1Boolean; 041import com.unboundid.asn1.ASN1Buffer; 042import com.unboundid.asn1.ASN1BufferSequence; 043import com.unboundid.asn1.ASN1Element; 044import com.unboundid.asn1.ASN1OctetString; 045import com.unboundid.asn1.ASN1Sequence; 046import com.unboundid.asn1.ASN1StreamReader; 047import com.unboundid.asn1.ASN1StreamReaderSequence; 048import com.unboundid.ldap.sdk.Control; 049import com.unboundid.ldap.sdk.LDAPException; 050import com.unboundid.ldap.sdk.ModifyDNRequest; 051import com.unboundid.ldap.sdk.ResultCode; 052import com.unboundid.util.Debug; 053import com.unboundid.util.InternalUseOnly; 054import com.unboundid.util.NotMutable; 055import com.unboundid.util.NotNull; 056import com.unboundid.util.Nullable; 057import com.unboundid.util.StaticUtils; 058import com.unboundid.util.ThreadSafety; 059import com.unboundid.util.ThreadSafetyLevel; 060 061import static com.unboundid.ldap.protocol.ProtocolMessages.*; 062 063 064 065/** 066 * This class provides an implementation of an LDAP modify DN request protocol 067 * op. 068 */ 069@InternalUseOnly() 070@NotMutable() 071@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 072public final class ModifyDNRequestProtocolOp 073 implements ProtocolOp 074{ 075 /** 076 * The BER type for the newSuperior element. 077 */ 078 public static final byte TYPE_NEW_SUPERIOR = (byte) 0x80; 079 080 081 082 /** 083 * The serial version UID for this serializable class. 084 */ 085 private static final long serialVersionUID = 7514385089303489375L; 086 087 088 089 // The deleteOldRDN flag for this modify DN request. 090 private final boolean deleteOldRDN; 091 092 // The entry DN for this modify DN request. 093 @NotNull private final String dn; 094 095 // The new RDN for this modify DN request. 096 @NotNull private final String newRDN; 097 098 // The new superior DN for this modify DN request. 099 @Nullable private final String newSuperiorDN; 100 101 102 103 /** 104 * Creates a new modify DN request protocol op with the provided information. 105 * 106 * @param dn The entry DN for this modify DN request. 107 * @param newRDN The new RDN for this modify DN request. 108 * @param deleteOldRDN Indicates whether to delete the old RDN values. 109 * @param newSuperiorDN The new superior DN for this modify DN request, or 110 * {@code null} if there is none. 111 */ 112 public ModifyDNRequestProtocolOp(@NotNull final String dn, 113 @NotNull final String newRDN, 114 final boolean deleteOldRDN, 115 @Nullable final String newSuperiorDN) 116 { 117 this.dn = dn; 118 this.newRDN = newRDN; 119 this.deleteOldRDN = deleteOldRDN; 120 this.newSuperiorDN = newSuperiorDN; 121 } 122 123 124 125 /** 126 * Creates a new modify DN request protocol op from the provided modify DN 127 * request object. 128 * 129 * @param request The modify DN request object to use to create this 130 * protocol op. 131 */ 132 public ModifyDNRequestProtocolOp(@NotNull final ModifyDNRequest request) 133 { 134 dn = request.getDN(); 135 newRDN = request.getNewRDN(); 136 deleteOldRDN = request.deleteOldRDN(); 137 newSuperiorDN = request.getNewSuperiorDN(); 138 } 139 140 141 142 /** 143 * Creates a new modify DN request protocol op read from the provided ASN.1 144 * stream reader. 145 * 146 * @param reader The ASN.1 stream reader from which to read the modify DN 147 * request protocol op. 148 * 149 * @throws LDAPException If a problem occurs while reading or parsing the 150 * modify DN request. 151 */ 152 ModifyDNRequestProtocolOp(@NotNull final ASN1StreamReader reader) 153 throws LDAPException 154 { 155 try 156 { 157 final ASN1StreamReaderSequence opSequence = reader.beginSequence(); 158 159 dn = reader.readString(); 160 newRDN = reader.readString(); 161 deleteOldRDN = reader.readBoolean(); 162 163 if (opSequence.hasMoreElements()) 164 { 165 newSuperiorDN = reader.readString(); 166 } 167 else 168 { 169 newSuperiorDN = null; 170 } 171 } 172 catch (final Exception e) 173 { 174 Debug.debugException(e); 175 176 throw new LDAPException(ResultCode.DECODING_ERROR, 177 ERR_MODIFY_DN_REQUEST_CANNOT_DECODE.get( 178 StaticUtils.getExceptionMessage(e)), 179 e); 180 } 181 } 182 183 184 185 /** 186 * Retrieves the target entry DN for this modify DN request. 187 * 188 * @return The target entry DN for this modify DN request. 189 */ 190 @NotNull() 191 public String getDN() 192 { 193 return dn; 194 } 195 196 197 198 /** 199 * Retrieves the new RDN for this modify DN request. 200 * 201 * @return The new RDN for this modify DN request. 202 */ 203 @NotNull() 204 public String getNewRDN() 205 { 206 return newRDN; 207 } 208 209 210 211 /** 212 * Indicates whether to delete the old RDN values from the target entry. 213 * 214 * @return {@code true} if the old RDN values should be removed from the 215 * entry, or {@code false} if not. 216 */ 217 public boolean deleteOldRDN() 218 { 219 return deleteOldRDN; 220 } 221 222 223 224 /** 225 * Retrieves the new superior DN for this modify DN request, if any. 226 * 227 * @return The new superior DN for this modify DN request, or {@code null} if 228 * there is none. 229 */ 230 @Nullable() 231 public String getNewSuperiorDN() 232 { 233 return newSuperiorDN; 234 } 235 236 237 238 /** 239 * {@inheritDoc} 240 */ 241 @Override() 242 public byte getProtocolOpType() 243 { 244 return LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST; 245 } 246 247 248 249 /** 250 * {@inheritDoc} 251 */ 252 @Override() 253 @NotNull() 254 public ASN1Element encodeProtocolOp() 255 { 256 if (newSuperiorDN == null) 257 { 258 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST, 259 new ASN1OctetString(dn), 260 new ASN1OctetString(newRDN), 261 new ASN1Boolean(deleteOldRDN)); 262 } 263 else 264 { 265 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST, 266 new ASN1OctetString(dn), 267 new ASN1OctetString(newRDN), 268 new ASN1Boolean(deleteOldRDN), 269 new ASN1OctetString(TYPE_NEW_SUPERIOR, newSuperiorDN)); 270 } 271 } 272 273 274 275 /** 276 * Decodes the provided ASN.1 element as a modify DN request protocol op. 277 * 278 * @param element The ASN.1 element to be decoded. 279 * 280 * @return The decoded modify DN request protocol op. 281 * 282 * @throws LDAPException If the provided ASN.1 element cannot be decoded as 283 * a modify DN request protocol op. 284 */ 285 @NotNull() 286 public static ModifyDNRequestProtocolOp decodeProtocolOp( 287 @NotNull final ASN1Element element) 288 throws LDAPException 289 { 290 try 291 { 292 final ASN1Element[] elements = 293 ASN1Sequence.decodeAsSequence(element).elements(); 294 final String dn = 295 ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 296 final String newRDN = 297 ASN1OctetString.decodeAsOctetString(elements[1]).stringValue(); 298 final boolean deleteOldRDN = 299 ASN1Boolean.decodeAsBoolean(elements[2]).booleanValue(); 300 301 final String newSuperiorDN; 302 if (elements.length > 3) 303 { 304 newSuperiorDN = 305 ASN1OctetString.decodeAsOctetString(elements[3]).stringValue(); 306 } 307 else 308 { 309 newSuperiorDN = null; 310 } 311 312 return new ModifyDNRequestProtocolOp(dn, newRDN, deleteOldRDN, 313 newSuperiorDN); 314 } 315 catch (final Exception e) 316 { 317 Debug.debugException(e); 318 throw new LDAPException(ResultCode.DECODING_ERROR, 319 ERR_MODIFY_DN_REQUEST_CANNOT_DECODE.get( 320 StaticUtils.getExceptionMessage(e)), 321 e); 322 } 323 } 324 325 326 327 /** 328 * {@inheritDoc} 329 */ 330 @Override() 331 public void writeTo(@NotNull final ASN1Buffer buffer) 332 { 333 final ASN1BufferSequence opSequence = 334 buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST); 335 buffer.addOctetString(dn); 336 buffer.addOctetString(newRDN); 337 buffer.addBoolean(deleteOldRDN); 338 339 if (newSuperiorDN != null) 340 { 341 buffer.addOctetString(TYPE_NEW_SUPERIOR, newSuperiorDN); 342 } 343 opSequence.end(); 344 } 345 346 347 348 /** 349 * Creates a modify DN request from this protocol op. 350 * 351 * @param controls The set of controls to include in the modify DN request. 352 * It may be empty or {@code null} if no controls should be 353 * included. 354 * 355 * @return The modify DN request that was created. 356 */ 357 @NotNull() 358 public ModifyDNRequest toModifyDNRequest(@Nullable final Control... controls) 359 { 360 return new ModifyDNRequest(dn, newRDN, deleteOldRDN, newSuperiorDN, 361 controls); 362 } 363 364 365 366 /** 367 * Retrieves a string representation of this protocol op. 368 * 369 * @return A string representation of this protocol op. 370 */ 371 @Override() 372 @NotNull() 373 public String toString() 374 { 375 final StringBuilder buffer = new StringBuilder(); 376 toString(buffer); 377 return buffer.toString(); 378 } 379 380 381 382 /** 383 * {@inheritDoc} 384 */ 385 @Override() 386 public void toString(@NotNull final StringBuilder buffer) 387 { 388 buffer.append("ModifyDNRequestProtocolOp(dn='"); 389 buffer.append(dn); 390 buffer.append("', newRDN='"); 391 buffer.append(newRDN); 392 buffer.append("', deleteOldRDN="); 393 buffer.append(deleteOldRDN); 394 395 if (newSuperiorDN != null) 396 { 397 buffer.append(", newSuperiorDN='"); 398 buffer.append(newSuperiorDN); 399 buffer.append('\''); 400 } 401 402 buffer.append(')'); 403 } 404}